Avatars on timelines improvements
This commit is contained in:
parent
776236b2f4
commit
14b9785af2
|
@ -1168,7 +1168,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 102;
|
CURRENT_PROJECT_VERSION = 104;
|
||||||
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = VernissageWidget/Info.plist;
|
INFOPLIST_FILE = VernissageWidget/Info.plist;
|
||||||
|
@ -1179,7 +1179,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.0;
|
MARKETING_VERSION = 1.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.widget;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.widget;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
@ -1196,7 +1196,7 @@
|
||||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 102;
|
CURRENT_PROJECT_VERSION = 104;
|
||||||
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = VernissageWidget/Info.plist;
|
INFOPLIST_FILE = VernissageWidget/Info.plist;
|
||||||
|
@ -1207,7 +1207,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.0;
|
MARKETING_VERSION = 1.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.widget;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.widget;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
@ -1223,7 +1223,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 102;
|
CURRENT_PROJECT_VERSION = 104;
|
||||||
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = VernissageShare/Info.plist;
|
INFOPLIST_FILE = VernissageShare/Info.plist;
|
||||||
|
@ -1235,7 +1235,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.0;
|
MARKETING_VERSION = 1.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.share;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.share;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
@ -1250,7 +1250,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 102;
|
CURRENT_PROJECT_VERSION = 104;
|
||||||
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = VernissageShare/Info.plist;
|
INFOPLIST_FILE = VernissageShare/Info.plist;
|
||||||
|
@ -1262,7 +1262,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.0;
|
MARKETING_VERSION = 1.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.share;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.share;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
|
@ -1399,7 +1399,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 102;
|
CURRENT_PROJECT_VERSION = 104;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
|
@ -1416,7 +1416,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.0;
|
MARKETING_VERSION = 1.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
@ -1439,7 +1439,7 @@
|
||||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||||
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 102;
|
CURRENT_PROJECT_VERSION = 104;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
DEVELOPMENT_TEAM = B2U9FEKYP8;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
|
@ -1456,7 +1456,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.0;
|
MARKETING_VERSION = 1.3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
|
|
|
@ -9,6 +9,7 @@ import Nuke
|
||||||
import NukeUI
|
import NukeUI
|
||||||
import ClientKit
|
import ClientKit
|
||||||
import EnvironmentKit
|
import EnvironmentKit
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct VernissageApp: App {
|
struct VernissageApp: App {
|
||||||
|
@ -66,6 +67,9 @@ struct VernissageApp: App {
|
||||||
await self.calculateNewPhotosInBackground()
|
await self.calculateNewPhotosInBackground()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reload widget content when application become active.
|
||||||
|
WidgetCenter.shared.reloadAllTimelines()
|
||||||
}
|
}
|
||||||
.onReceive(timer) { _ in
|
.onReceive(timer) { _ in
|
||||||
Task {
|
Task {
|
||||||
|
|
|
@ -12,18 +12,18 @@ import ServicesKit
|
||||||
import EnvironmentKit
|
import EnvironmentKit
|
||||||
|
|
||||||
public extension View {
|
public extension View {
|
||||||
func imageAvatar(applicationState: ApplicationState, displayName: String?, avatarUrl: URL?) -> some View {
|
func imageAvatar(displayName: String?, avatarUrl: URL?) -> some View {
|
||||||
modifier(ImageAvatar(applicationState: applicationState, displayName: displayName, avatarUrl: avatarUrl))
|
modifier(ImageAvatar(displayName: displayName, avatarUrl: avatarUrl))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct ImageAvatar: ViewModifier {
|
private struct ImageAvatar: ViewModifier {
|
||||||
private let applicationState: ApplicationState
|
@EnvironmentObject var applicationState: ApplicationState
|
||||||
|
|
||||||
private let displayName: String?
|
private let displayName: String?
|
||||||
private let avatarUrl: URL?
|
private let avatarUrl: URL?
|
||||||
|
|
||||||
init(applicationState: ApplicationState, displayName: String?, avatarUrl: URL?) {
|
init(displayName: String?, avatarUrl: URL?) {
|
||||||
self.applicationState = applicationState
|
|
||||||
self.displayName = displayName
|
self.displayName = displayName
|
||||||
self.avatarUrl = avatarUrl
|
self.avatarUrl = avatarUrl
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,22 +10,22 @@ import ClientKit
|
||||||
import ServicesKit
|
import ServicesKit
|
||||||
|
|
||||||
public extension View {
|
public extension View {
|
||||||
func imageContextMenu(client: Client, statusModel: StatusModel) -> some View {
|
func imageContextMenu(statusModel: StatusModel) -> some View {
|
||||||
modifier(ImageContextMenu(client: client, id: statusModel.id, url: statusModel.url))
|
modifier(ImageContextMenu(id: statusModel.id, url: statusModel.url))
|
||||||
}
|
}
|
||||||
|
|
||||||
func imageContextMenu(client: Client, statusData: StatusData) -> some View {
|
func imageContextMenu(statusData: StatusData) -> some View {
|
||||||
modifier(ImageContextMenu(client: client, id: statusData.id, url: statusData.url))
|
modifier(ImageContextMenu(id: statusData.id, url: statusData.url))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct ImageContextMenu: ViewModifier {
|
private struct ImageContextMenu: ViewModifier {
|
||||||
private let client: Client
|
@EnvironmentObject var client: Client
|
||||||
|
|
||||||
private let id: String
|
private let id: String
|
||||||
private let url: URL?
|
private let url: URL?
|
||||||
|
|
||||||
init(client: Client, id: String, url: URL?) {
|
init(id: String, url: URL?) {
|
||||||
self.client = client
|
|
||||||
self.id = id
|
self.id = id
|
||||||
self.url = url
|
self.url = url
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,10 +121,9 @@ struct ImageRowItem: View {
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
self.navigateToStatus()
|
self.navigateToStatus()
|
||||||
}
|
}
|
||||||
.imageAvatar(applicationState: self.applicationState,
|
.imageAvatar(displayName: self.status.accountDisplayName,
|
||||||
displayName: self.status.accountDisplayName,
|
|
||||||
avatarUrl: self.status.accountAvatar)
|
avatarUrl: self.status.accountAvatar)
|
||||||
.imageContextMenu(client: self.client, statusData: self.status)
|
.imageContextMenu(statusData: self.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func downloadImage(attachmentData: AttachmentData) async {
|
private func downloadImage(attachmentData: AttachmentData) async {
|
||||||
|
|
|
@ -128,11 +128,10 @@ struct ImageRowItemAsync: View {
|
||||||
self.navigateToStatus()
|
self.navigateToStatus()
|
||||||
}
|
}
|
||||||
.if(self.showAvatar) {
|
.if(self.showAvatar) {
|
||||||
$0.imageAvatar(applicationState: self.applicationState,
|
$0.imageAvatar(displayName: self.statusViewModel.account.displayNameWithoutEmojis,
|
||||||
displayName: self.statusViewModel.account.displayNameWithoutEmojis,
|
|
||||||
avatarUrl: self.statusViewModel.account.avatar)
|
avatarUrl: self.statusViewModel.account.avatar)
|
||||||
}
|
}
|
||||||
.imageContextMenu(client: self.client, statusModel: self.statusViewModel)
|
.imageContextMenu(statusModel: self.statusViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func navigateToStatus() {
|
private func navigateToStatus() {
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class ImageFetcher {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let displayDate = Calendar.current.date(byAdding: .minute, value: widgetEntries.count * 15, to: Date())
|
let displayDate = Calendar.current.date(byAdding: .minute, value: widgetEntries.count * 20, to: Date())
|
||||||
|
|
||||||
widgetEntries.append(WidgetEntry(date: displayDate ?? Date(),
|
widgetEntries.append(WidgetEntry(date: displayDate ?? Date(),
|
||||||
image: uiImage,
|
image: uiImage,
|
||||||
|
@ -67,7 +67,7 @@ public class ImageFetcher {
|
||||||
widgetEntries.append(self.placeholder())
|
widgetEntries.append(self.placeholder())
|
||||||
}
|
}
|
||||||
|
|
||||||
return widgetEntries
|
return widgetEntries.shuffled()
|
||||||
}
|
}
|
||||||
|
|
||||||
func placeholder() -> WidgetEntry {
|
func placeholder() -> WidgetEntry {
|
||||||
|
|
|
@ -31,13 +31,13 @@ struct Provider: TimelineProvider {
|
||||||
let currentDate = Date()
|
let currentDate = Date()
|
||||||
let widgetEntries = await self.getWidgetEntries()
|
let widgetEntries = await self.getWidgetEntries()
|
||||||
|
|
||||||
let nextUpdateDate = Calendar.current.date(byAdding: .hour, value: 2, to: currentDate)!
|
let nextUpdateDate = Calendar.current.date(byAdding: .hour, value: 1, to: currentDate)!
|
||||||
let timeline = Timeline(entries: widgetEntries, policy: .after(nextUpdateDate))
|
let timeline = Timeline(entries: widgetEntries, policy: .after(nextUpdateDate))
|
||||||
completion(timeline)
|
completion(timeline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWidgetEntries(length: Int = 8) async -> [WidgetEntry] {
|
func getWidgetEntries(length: Int = 3) async -> [WidgetEntry] {
|
||||||
do {
|
do {
|
||||||
return try await ImageFetcher.shared.fetchWidgetEntries(length: length)
|
return try await ImageFetcher.shared.fetchWidgetEntries(length: length)
|
||||||
} catch {
|
} catch {
|
||||||
|
|
Loading…
Reference in New Issue