Improve counter on home timeline
This commit is contained in:
parent
2a44115bd8
commit
facc2caf5f
|
@ -13,7 +13,7 @@ extension Client {
|
|||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40,
|
||||
includeReblogs: Bool? = nil) async throws -> [Status] {
|
||||
includeReblogs: Bool? = nil) async throws -> Linkable<[Status]> {
|
||||
return try await pixelfedClient.getHomeTimeline(maxId: maxId, sinceId: sinceId, minId: minId, limit: limit, includeReblogs: includeReblogs)
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ extension Client {
|
|||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
limit: Int = 40) async throws -> Linkable<[Status]> {
|
||||
return try await pixelfedClient.getPublicTimeline(local: local,
|
||||
remote: remote,
|
||||
onlyMedia: true,
|
||||
|
@ -38,7 +38,7 @@ extension Client {
|
|||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
limit: Int = 40) async throws -> Linkable<[Status]> {
|
||||
return try await pixelfedClient.getTagTimeline(tag: tag,
|
||||
local: local,
|
||||
remote: remote,
|
||||
|
|
|
@ -64,7 +64,7 @@ class AccountDataHandler {
|
|||
}
|
||||
}
|
||||
|
||||
func update(lastSeenStatusId: String?, lastLoadedStatusId: String?, statuses: [Status]? = nil, applicationState: ApplicationState, modelContext: ModelContext) throws {
|
||||
func update(lastSeenStatusId: String?, lastLoadedStatusId: String?, statuses: Linkable<[Status]>? = nil, applicationState: ApplicationState, modelContext: ModelContext) throws {
|
||||
guard let accountId = applicationState.account?.id else {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -237,6 +237,34 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"+99" : {
|
||||
"localizations" : {
|
||||
"es" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "+99"
|
||||
}
|
||||
},
|
||||
"eu" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "+99"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "+99"
|
||||
}
|
||||
},
|
||||
"pl" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "+99"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"accounts.error.loadingAccountsFailed" : {
|
||||
"comment" : "Information message when loading account failed",
|
||||
"localizations" : {
|
||||
|
|
|
@ -8,7 +8,7 @@ import Foundation
|
|||
import RegexBuilder
|
||||
|
||||
/// Link returned in header for paging feature/
|
||||
public struct Link {
|
||||
public struct Link: Codable {
|
||||
|
||||
/// Raw value of header link.
|
||||
public let rawLink: String
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import Foundation
|
||||
|
||||
/// Some of endpoint returns JSON data and additional information in header, like link for paging functionality.
|
||||
public struct Linkable<T> where T: Codable {
|
||||
public struct Linkable<T> : Codable where T: Codable {
|
||||
|
||||
/// Data retunred in HTTP reponse body (mostly JSON data/entities).
|
||||
public let data: T
|
||||
|
@ -20,3 +20,29 @@ public struct Linkable<T> where T: Codable {
|
|||
self.link = link
|
||||
}
|
||||
}
|
||||
|
||||
public extension Linkable<[Status]> {
|
||||
func getMinId() -> String? {
|
||||
if let link = self.link {
|
||||
return link.minId
|
||||
}
|
||||
|
||||
if let firstItemId = self.data.first?.id {
|
||||
return firstItemId
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMaxId() -> String? {
|
||||
if let link = self.link {
|
||||
return link.maxId
|
||||
}
|
||||
|
||||
if let lastItemId = self.data.last?.id {
|
||||
return lastItemId
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public extension PixelfedClientAuthenticated {
|
|||
minId: EntityId? = nil,
|
||||
limit: Int? = nil,
|
||||
includeReblogs: Bool? = nil,
|
||||
timeoutInterval: Double? = nil) async throws -> [Status] {
|
||||
timeoutInterval: Double? = nil) async throws -> Linkable<[Status]> {
|
||||
|
||||
let request = try Self.request(
|
||||
for: baseURL,
|
||||
|
@ -22,7 +22,7 @@ public extension PixelfedClientAuthenticated {
|
|||
timeoutInterval: timeoutInterval
|
||||
)
|
||||
|
||||
return try await downloadJson([Status].self, request: request)
|
||||
return try await downloadJsonWithLink([Status].self, request: request)
|
||||
}
|
||||
|
||||
func getPublicTimeline(local: Bool? = nil,
|
||||
|
@ -31,7 +31,7 @@ public extension PixelfedClientAuthenticated {
|
|||
maxId: EntityId? = nil,
|
||||
sinceId: EntityId? = nil,
|
||||
minId: EntityId? = nil,
|
||||
limit: Limit? = nil) async throws -> [Status] {
|
||||
limit: Limit? = nil) async throws -> Linkable<[Status]> {
|
||||
|
||||
let request = try Self.request(
|
||||
for: baseURL,
|
||||
|
@ -39,7 +39,7 @@ public extension PixelfedClientAuthenticated {
|
|||
withBearerToken: token
|
||||
)
|
||||
|
||||
return try await downloadJson([Status].self, request: request)
|
||||
return try await downloadJsonWithLink([Status].self, request: request)
|
||||
}
|
||||
|
||||
func getTagTimeline(tag: String,
|
||||
|
@ -49,7 +49,7 @@ public extension PixelfedClientAuthenticated {
|
|||
maxId: EntityId? = nil,
|
||||
sinceId: EntityId? = nil,
|
||||
minId: EntityId? = nil,
|
||||
limit: Int? = nil) async throws -> [Status] {
|
||||
limit: Int? = nil) async throws -> Linkable<[Status]> {
|
||||
|
||||
let request = try Self.request(
|
||||
for: baseURL,
|
||||
|
@ -57,7 +57,7 @@ public extension PixelfedClientAuthenticated {
|
|||
withBearerToken: token
|
||||
)
|
||||
|
||||
return try await downloadJson([Status].self, request: request)
|
||||
return try await downloadJsonWithLink([Status].self, request: request)
|
||||
}
|
||||
|
||||
func setMarkers(_ markers: [Pixelfed.Markers.Timeline: EntityId]) async throws -> Markers {
|
||||
|
|
|
@ -1209,7 +1209,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.1;
|
||||
MARKETING_VERSION = 2.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.widget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
|
@ -1243,7 +1243,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.1;
|
||||
MARKETING_VERSION = 2.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.widget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
|
@ -1276,7 +1276,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.1;
|
||||
MARKETING_VERSION = 2.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.share;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
|
@ -1308,7 +1308,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.1;
|
||||
MARKETING_VERSION = 2.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.share;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
|
@ -1474,7 +1474,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.1;
|
||||
MARKETING_VERSION = 2.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
@ -1517,7 +1517,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.1;
|
||||
MARKETING_VERSION = 2.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
|
|
|
@ -43,27 +43,49 @@ public class HomeTimelineService {
|
|||
|
||||
let client = PixelfedClient(baseURL: accountData.serverUrl).getAuthenticated(token: accessToken)
|
||||
var statuses: [Status] = []
|
||||
var newestStatusId = lastSeenStatusId
|
||||
var latestStatusId: String? = nil
|
||||
var breakProcesssing = false;
|
||||
|
||||
// There can be more then 40 newest statuses, that's why we have to sometimes send more then one request.
|
||||
while true {
|
||||
do {
|
||||
let downloadedStatuses = try await client.getHomeTimeline(minId: newestStatusId,
|
||||
// Download statuses from the top or the list.
|
||||
let downloadedStatuses = try await client.getHomeTimeline(maxId: latestStatusId,
|
||||
limit: self.maximumAmountOfDownloadedStatuses,
|
||||
includeReblogs: includeReblogs)
|
||||
|
||||
guard let firstStatus = downloadedStatuses.first else {
|
||||
break
|
||||
// Iterate througt the list until we go to already visible status by the user.
|
||||
var temporaryList: [Status] = []
|
||||
for downloadedStatus in downloadedStatuses.data {
|
||||
guard downloadedStatus.id != lastSeenStatusId else {
|
||||
breakProcesssing = true
|
||||
break
|
||||
}
|
||||
|
||||
temporaryList.append(downloadedStatus)
|
||||
}
|
||||
|
||||
|
||||
// Remove from the list duplicated statuses.
|
||||
let visibleStatuses = self.getVisibleStatuses(accountId: accountData.id,
|
||||
statuses: downloadedStatuses,
|
||||
statuses: temporaryList,
|
||||
hideStatusesWithoutAlt: hideStatusesWithoutAlt,
|
||||
modelContext: modelContext)
|
||||
|
||||
|
||||
// Add statuses to the list.
|
||||
statuses.append(contentsOf: visibleStatuses)
|
||||
|
||||
newestStatusId = firstStatus.id
|
||||
// Break when we go to the already visible status.
|
||||
if breakProcesssing {
|
||||
break
|
||||
}
|
||||
|
||||
// When we discovered more then 100 statuses we can break.
|
||||
if statuses.count > 100 {
|
||||
break
|
||||
}
|
||||
|
||||
// Set status Id which should be used to download next portion of the statuses.
|
||||
latestStatusId = downloadedStatuses.getMaxId()
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "global.error.errorDuringDownloadingNewStatuses")
|
||||
break
|
||||
|
|
|
@ -143,8 +143,14 @@ struct HomeTimelineView: View {
|
|||
HStack {
|
||||
Image(systemName: "arrow.up")
|
||||
.fontWeight(.light)
|
||||
Text("\(self.applicationState.amountOfNewStatuses)")
|
||||
.fontWeight(.semibold)
|
||||
|
||||
if self.applicationState.amountOfNewStatuses < 100 {
|
||||
Text("\(self.applicationState.amountOfNewStatuses)")
|
||||
.fontWeight(.semibold)
|
||||
} else {
|
||||
Text("+99")
|
||||
.fontWeight(.semibold)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 12)
|
||||
.padding(.horizontal, 18)
|
||||
|
@ -183,28 +189,28 @@ struct HomeTimelineView: View {
|
|||
// Download statuses from API (which are older then last visible status).
|
||||
let statuses = try await self.loadFromCacheOrApi(timelineCache: accountData.timelineCache)
|
||||
|
||||
if statuses.isEmpty {
|
||||
if statuses.data.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
return
|
||||
}
|
||||
|
||||
// Remember last status id returned by API.
|
||||
self.lastStatusId = statuses.last?.id
|
||||
self.lastStatusId = statuses.getMaxId()
|
||||
|
||||
// Get only visible statuses.
|
||||
let visibleStatuses = HomeTimelineService.shared.getVisibleStatuses(accountId: accountId,
|
||||
statuses: statuses,
|
||||
statuses: statuses.data,
|
||||
hideStatusesWithoutAlt: self.applicationState.hideStatusesWithoutAlt,
|
||||
modelContext: modelContext)
|
||||
|
||||
// Remeber first status returned by API in user context (when it's newer then remembered).
|
||||
try AccountDataHandler.shared.update(lastSeenStatusId: nil,
|
||||
lastLoadedStatusId: statuses.first?.id,
|
||||
lastLoadedStatusId: statuses.getMinId(),
|
||||
applicationState: self.applicationState,
|
||||
modelContext: modelContext)
|
||||
|
||||
// Append statuses to viewed.
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses, accountId: accountId, modelContext: modelContext)
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses.data, accountId: accountId, modelContext: modelContext)
|
||||
|
||||
// Map to view models.
|
||||
let statusModels = visibleStatuses.map({ StatusModel(status: $0) })
|
||||
|
@ -222,24 +228,24 @@ struct HomeTimelineView: View {
|
|||
// Download statuses from API.
|
||||
let statuses = try await self.loadFromApi(maxId: lastStatusId)
|
||||
|
||||
if statuses.isEmpty {
|
||||
if statuses.data.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
return
|
||||
}
|
||||
|
||||
// Now we have new last status.
|
||||
if let lastStatusId = statuses.last?.id {
|
||||
if let lastStatusId = statuses.getMaxId() {
|
||||
self.lastStatusId = lastStatusId
|
||||
}
|
||||
|
||||
// Get only visible statuses.
|
||||
let visibleStatuses = HomeTimelineService.shared.getVisibleStatuses(accountId: accountId,
|
||||
statuses: statuses,
|
||||
statuses: statuses.data,
|
||||
hideStatusesWithoutAlt: self.applicationState.hideStatusesWithoutAlt,
|
||||
modelContext: modelContext)
|
||||
|
||||
// Append statuses to viewed.
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses, accountId: accountId, modelContext: modelContext)
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses.data, accountId: accountId, modelContext: modelContext)
|
||||
|
||||
// Map to view models.
|
||||
let statusModels = visibleStatuses.map({ StatusModel(status: $0) })
|
||||
|
@ -260,29 +266,29 @@ struct HomeTimelineView: View {
|
|||
// Download statuses from API.
|
||||
let statuses = try await self.loadFromApi()
|
||||
|
||||
if statuses.isEmpty {
|
||||
if statuses.data.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
return
|
||||
}
|
||||
|
||||
// Remember last status id returned by API.
|
||||
self.lastStatusId = statuses.last?.id
|
||||
self.lastStatusId = statuses.getMaxId()
|
||||
|
||||
// Get only visible statuses.
|
||||
let visibleStatuses = HomeTimelineService.shared.getVisibleStatuses(accountId: accountId,
|
||||
statuses: statuses,
|
||||
statuses: statuses.data,
|
||||
hideStatusesWithoutAlt: self.applicationState.hideStatusesWithoutAlt,
|
||||
modelContext: modelContext)
|
||||
|
||||
// Remeber first status returned by API in user context (when it's newer then remembered).
|
||||
try AccountDataHandler.shared.update(lastSeenStatusId: self.statusViewModels.first?.id,
|
||||
lastLoadedStatusId: statuses.first?.id,
|
||||
lastLoadedStatusId: statuses.getMinId(),
|
||||
statuses: statuses,
|
||||
applicationState: self.applicationState,
|
||||
modelContext: modelContext)
|
||||
|
||||
// Append statuses to viewed.
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses, accountId: accountId, modelContext: modelContext)
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses.data, accountId: accountId, modelContext: modelContext)
|
||||
|
||||
// Map to view models.
|
||||
let statusModels = visibleStatuses.map({ StatusModel(status: $0) })
|
||||
|
@ -297,24 +303,22 @@ struct HomeTimelineView: View {
|
|||
self.applicationState.amountOfNewStatuses = 0
|
||||
}
|
||||
|
||||
private func loadFromCacheOrApi(timelineCache: String?) async throws -> [Status] {
|
||||
if let timelineCache, let timelineCacheData = timelineCache.data(using: .utf8) {
|
||||
let statusesFromCache = try? JSONDecoder().decode([Status].self, from: timelineCacheData)
|
||||
if let statusesFromCache {
|
||||
return statusesFromCache
|
||||
}
|
||||
private func loadFromCacheOrApi(timelineCache: String?) async throws -> Linkable<[Status]> {
|
||||
if let timelineCache, let timelineCacheData = timelineCache.data(using: .utf8),
|
||||
let statusesFromCache = try? JSONDecoder().decode(Linkable<[Status]>.self, from: timelineCacheData) {
|
||||
return statusesFromCache
|
||||
}
|
||||
|
||||
return try await self.loadFromApi()
|
||||
}
|
||||
|
||||
private func loadFromApi(maxId: String? = nil, sinceId: String? = nil, minId: String? = nil) async throws -> [Status] {
|
||||
private func loadFromApi(maxId: String? = nil, sinceId: String? = nil, minId: String? = nil) async throws -> Linkable<[Status]> {
|
||||
return try await self.client.publicTimeline?.getHomeTimeline(
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit,
|
||||
includeReblogs: self.applicationState.showReboostedStatuses) ?? []
|
||||
includeReblogs: self.applicationState.showReboostedStatuses) ?? Linkable(data: [])
|
||||
}
|
||||
|
||||
private func calculateOffset() {
|
||||
|
|
|
@ -182,29 +182,29 @@ struct StatusesView: View {
|
|||
|
||||
let statuses = try await self.loadFromApi()
|
||||
|
||||
if statuses.isEmpty {
|
||||
if statuses.data.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
return
|
||||
}
|
||||
|
||||
// Remember last status id returned by API.
|
||||
self.lastStatusId = statuses.last?.id
|
||||
self.lastStatusId = statuses.getMaxId()
|
||||
|
||||
// Get only visible statuses.
|
||||
let visibleStatuses = HomeTimelineService.shared.getVisibleStatuses(accountId: accountId,
|
||||
statuses: statuses,
|
||||
statuses: statuses.data,
|
||||
hideStatusesWithoutAlt: self.applicationState.hideStatusesWithoutAlt,
|
||||
modelContext: modelContext)
|
||||
|
||||
if self.listType == .home {
|
||||
// Remeber first status returned by API in user context (when it's newer then remembered).
|
||||
try AccountDataHandler.shared.update(lastSeenStatusId: nil,
|
||||
lastLoadedStatusId: statuses.first?.id,
|
||||
lastLoadedStatusId: statuses.getMinId(),
|
||||
applicationState: self.applicationState,
|
||||
modelContext: modelContext)
|
||||
|
||||
// Append statuses to viewed.
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses, accountId: accountId, modelContext: modelContext)
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses.data, accountId: accountId, modelContext: modelContext)
|
||||
}
|
||||
|
||||
// Map to view models.
|
||||
|
@ -221,25 +221,25 @@ struct StatusesView: View {
|
|||
if let lastStatusId = self.lastStatusId, let accountId = self.applicationState.account?.id {
|
||||
let statuses = try await self.loadFromApi(maxId: lastStatusId)
|
||||
|
||||
if statuses.isEmpty {
|
||||
if statuses.data.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
return
|
||||
}
|
||||
|
||||
// Now we have new last status.
|
||||
if let lastStatusId = statuses.last?.id {
|
||||
if let lastStatusId = statuses.getMaxId() {
|
||||
self.lastStatusId = lastStatusId
|
||||
}
|
||||
|
||||
// Get only visible statuses.
|
||||
let visibleStatuses = HomeTimelineService.shared.getVisibleStatuses(accountId: accountId,
|
||||
statuses: statuses,
|
||||
statuses: statuses.data,
|
||||
hideStatusesWithoutAlt: self.applicationState.hideStatusesWithoutAlt,
|
||||
modelContext: modelContext)
|
||||
|
||||
if self.listType == .home {
|
||||
// Append statuses to viewed.
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses, accountId: accountId, modelContext: modelContext)
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses.data, accountId: accountId, modelContext: modelContext)
|
||||
}
|
||||
|
||||
// Map to view models.
|
||||
|
@ -260,29 +260,29 @@ struct StatusesView: View {
|
|||
|
||||
let statuses = try await self.loadFromApi()
|
||||
|
||||
if statuses.isEmpty {
|
||||
if statuses.data.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
return
|
||||
}
|
||||
|
||||
// Remember last status id returned by API.
|
||||
self.lastStatusId = statuses.last?.id
|
||||
self.lastStatusId = statuses.getMaxId()
|
||||
|
||||
// Get only visible statuses.
|
||||
let visibleStatuses = HomeTimelineService.shared.getVisibleStatuses(accountId: accountId,
|
||||
statuses: statuses,
|
||||
statuses: statuses.data,
|
||||
hideStatusesWithoutAlt: self.applicationState.hideStatusesWithoutAlt,
|
||||
modelContext: modelContext)
|
||||
|
||||
if self.listType == .home {
|
||||
// Remeber first status returned by API in user context (when it's newer then remembered).
|
||||
try AccountDataHandler.shared.update(lastSeenStatusId: self.statusViewModels.first?.id,
|
||||
lastLoadedStatusId: statuses.first?.id,
|
||||
lastLoadedStatusId: statuses.getMinId(),
|
||||
applicationState: self.applicationState,
|
||||
modelContext: modelContext)
|
||||
|
||||
// Append statuses to viewed.
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses, accountId: accountId, modelContext: modelContext)
|
||||
try ViewedStatusHandler.shared.append(contentsOf: statuses.data, accountId: accountId, modelContext: modelContext)
|
||||
}
|
||||
|
||||
// Map to view models.
|
||||
|
@ -296,7 +296,7 @@ struct StatusesView: View {
|
|||
self.statusViewModels = statusModels
|
||||
}
|
||||
|
||||
private func loadFromApi(maxId: String? = nil, sinceId: String? = nil, minId: String? = nil) async throws -> [Status] {
|
||||
private func loadFromApi(maxId: String? = nil, sinceId: String? = nil, minId: String? = nil) async throws -> Linkable<[Status]> {
|
||||
switch self.listType {
|
||||
case .home:
|
||||
return try await self.client.publicTimeline?.getHomeTimeline(
|
||||
|
@ -304,40 +304,44 @@ struct StatusesView: View {
|
|||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit,
|
||||
includeReblogs: self.applicationState.showReboostedStatuses) ?? []
|
||||
includeReblogs: self.applicationState.showReboostedStatuses) ?? Linkable(data: [])
|
||||
case .local:
|
||||
return try await self.client.publicTimeline?.getStatuses(
|
||||
local: true,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit) ?? []
|
||||
limit: self.defaultLimit) ?? Linkable(data: [])
|
||||
case .federated:
|
||||
return try await self.client.publicTimeline?.getStatuses(
|
||||
remote: true,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit) ?? []
|
||||
limit: self.defaultLimit) ?? Linkable(data: [])
|
||||
case .favourites:
|
||||
return try await self.client.accounts?.favourites(
|
||||
let favourites = try await self.client.accounts?.favourites(
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit) ?? []
|
||||
|
||||
return Linkable(data: favourites)
|
||||
case .bookmarks:
|
||||
return try await self.client.accounts?.bookmarks(
|
||||
let bookmarks = try await self.client.accounts?.bookmarks(
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit) ?? []
|
||||
|
||||
return Linkable(data: bookmarks)
|
||||
case .hashtag(let tag):
|
||||
let hashtagsFromApi = try await self.client.search?.search(query: tag, resultsType: .hashtags)
|
||||
guard let hashtagsFromApi = hashtagsFromApi, hashtagsFromApi.hashtags.isEmpty == false else {
|
||||
ToastrService.shared.showError(title: LocalizedStringResource("global.error.hashtagNotExists"), imageSystemName: "exclamationmark.octagon")
|
||||
dismiss()
|
||||
|
||||
return []
|
||||
return Linkable(data: [])
|
||||
}
|
||||
|
||||
return try await self.client.publicTimeline?.getTagStatuses(
|
||||
|
@ -345,7 +349,7 @@ struct StatusesView: View {
|
|||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit) ?? []
|
||||
limit: self.defaultLimit) ?? Linkable(data: [])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ struct ImagesGrid: View {
|
|||
do {
|
||||
let statusesFromApi = try await self.loadStatuses()
|
||||
|
||||
let statusesWithImages = statusesFromApi.getStatusesWithImagesOnly()
|
||||
let statusesWithImages = statusesFromApi.data.getStatusesWithImagesOnly()
|
||||
|
||||
let photoUrls = self.getPhotoUrls(statuses: statusesWithImages)
|
||||
self.prefetch(photoUrls: photoUrls)
|
||||
|
@ -119,15 +119,21 @@ struct ImagesGrid: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func loadStatuses() async throws -> [Status] {
|
||||
private func loadStatuses() async throws -> Linkable<[Status]> {
|
||||
switch self.gridType {
|
||||
case .hashtag(let name):
|
||||
return try await self.client.publicTimeline?.getTagStatuses(
|
||||
tag: name,
|
||||
local: true,
|
||||
limit: 10) ?? []
|
||||
limit: 10) ?? Linkable(data: [])
|
||||
case .account(let accountId, _, _):
|
||||
return try await self.client.accounts?.statuses(createdBy: accountId, onlyMedia: true, limit: 10) ?? []
|
||||
let accountStatuses = try await self.client.accounts?.statuses(
|
||||
createdBy: accountId,
|
||||
onlyMedia: true,
|
||||
limit: 10
|
||||
) ?? []
|
||||
|
||||
return Linkable(data: accountStatuses)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ public class StatusFetcher {
|
|||
let client = PixelfedClient(baseURL: account.serverUrl).getAuthenticated(token: accessToken)
|
||||
let statuses = try await client.getHomeTimeline(limit: 20, includeReblogs: defaultSettings.showReboostedStatuses, timeoutInterval: 5.0)
|
||||
|
||||
let widgetEntries = await self.prepare(statuses: statuses, length: length)
|
||||
let widgetEntries = await self.prepare(statuses: statuses.data, length: length)
|
||||
return widgetEntries
|
||||
}
|
||||
|
||||
|
@ -49,11 +49,11 @@ public class StatusFetcher {
|
|||
let accountData = AccountDataHandler.shared.getAccountData(accountId: accountId, modelContext: modelContext)
|
||||
guard let timelineCache = accountData?.timelineCache,
|
||||
let timelineCacheData = timelineCache.data(using: .utf8),
|
||||
let statusesFromCache = try? JSONDecoder().decode([Status].self, from: timelineCacheData) else {
|
||||
let statusesFromCache = try? JSONDecoder().decode(Linkable<[Status]>.self, from: timelineCacheData) else {
|
||||
return [self.placeholder()]
|
||||
}
|
||||
|
||||
let widgetEntries = await self.prepare(statuses: statusesFromCache, length: length)
|
||||
let widgetEntries = await self.prepare(statuses: statusesFromCache.data, length: length)
|
||||
return widgetEntries
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue