-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Feature: Jetpack Activity Logs #24597
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
108 commits
Select commit
Hold shift + click to select a range
c44a4c4
Add PaginatedResponse
kean 9ab1930
Refactor PaginatedResponse to DataViewPaginatedResponse
kean 48d56ee
Fix deleteItem to update total count
kean 96824f9
Rename LoadMoreFooterView
kean 4bd0903
Add DataViewPaginatedForEach component
kean 86903ee
Add DataViewPaginatedResponseProtocol
kean a2f5eba
Refactor subscribers to use DataViewPaginatedResponse
kean 077a2de
Refactor subscribers service creation and move deleteSubscriber exten…
kean d882b55
Fix typo in Subscriber
kean 9157192
Fix formatting
kean c07e5bc
Fix typos and address comments
kean f99f95c
Merge branch 'trunk' into task/activity-logs-swiftui
kean 96f9cfd
Implement new Jetpack Activity Logs screen
kean e61dbf3
Extract DataViewPaginatedResponse (#24592)
kean 28352d3
Implement Jetpack Activity Logs screen (list) (#24596)
kean 79dd91c
Fix SwiftLint warnings
kean 2b0dba8
Add Miniature app
kean 3063455
Add XcodeTarget_App as a dependency
kean 6f94f9e
Configure xcconfig (just use Reader)
kean bb8ce34
Add Miniature App (#24598)
kean e220263
Add initial ActivityLogDetailsView
kean 4526022
Add ActivityLogDetailsView to Miniature target
kean 6b1ed24
Extract Activity icon methods from WPStyleGuide to Activity extension
kean 8d3e826
Remove rewindStatus parameter from ActivityLogDetailsView
kean b0be437
Dev
kean fe65050
Add formattedContent
kean 4567c26
Move the code to the main target
kean 149a2fe
Extract reusable ActivityActorAvatarView
kean a312022
Remove unused code and integrate ActivityLogDetailsView
kean c02e30c
Fix SwiftLint warnings
kean 8f7cced
Add ActivityLogsDetailsView (#24599)
kean 6decdf8
Add initial restore/download backup code
kean cfdd76d
Remove JetpackSiteRef usages
kean b2e3c1c
Add multisite handling
kean e57f31c
Remove the new screens and use the existing flows
kean f6624ce
Add analytics
kean cbf1b14
Cleanup
kean d3d4bb6
Add missing analytics
kean 053cd42
Cleanup
kean 16c4c6e
Fix an issue with not all restorable acitivies shown in backups
kean d7bdf75
Fix an issue with restore/download flow layout
kean 2ece5e9
Show restore checkpoint in section
kean 4af44a5
Extract reusable CardView and InfoRow components from SubscribersDeta…
kean ea903d7
Cleanup
kean 0e67f85
Add Restore and Download Backup buttons to ActivityLogDetailsView (#2…
kean 5e60653
Add rewindable
kean 31f862d
Move restore buttons higher
kean d764d47
Add date filtering back
kean 1398936
Use ActivityLogsView to show Backups (#24601)
kean 54d3c39
Add Backup tracking
kean 7df96bd
Fix clear background in restore flows
kean 6b72d76
Rework how we do polling
kean 76c354a
Rework how we manage backup statuss
kean 64d1585
Revert hasBackup change
kean 5d41e39
Update tests
kean 36ea180
Add Downloadable Backup Section to Backups list (#24602)
kean 90d741b
Update release notes
kean 0e89ba3
Remove unused code
kean 5384608
Cleanup
kean 9325a27
Remove Application from list
kean 44972b9
Update Dashboard to use new ActivityLogsView (#24603)
kean 1c8dc6f
Remove BackupListViewController and use ActivityLogsViewController in…
kean 10e878a
Remove JetpackActivityLogViewController and use ActivityLogsViewContr…
kean cedbc2c
Remove dataViews feature flag
kean cc1719c
Create separate BackupsViewController and remove isBackupMode from Ac…
kean 33b40bf
Activity Logs: Code Removal – Part 1 (#24604)
kean e376f30
Remove ActivityListViewModelTests
kean 8957b9f
Remove ActivityTypeSelectorViewController
kean 07a1f60
Remove ActivityListViewModel
kean b8dd674
Remove BaseActivityListViewController
kean e8022ec
Fix compilation
kean 6e17279
Activity Logs: Code Removal – Part 2 (#24605)
kean 23aa07a
Remove RewindStatusRow
kean bb07b08
Remove RewindStatusTableViewCell
kean fe68785
Remove ActivityListRow
kean 43d84b6
Remove ActivityTableViewCell
kean 525b647
Activity Logs: Code Removal – Part 3 (#24606)
kean 733f01a
Remove CalendarViewController
kean c0ac5bb
Remove JTAppleCalendar dependency
kean ffda5bf
Activity Logs: Code Removal – Part 4 (#24607)
kean 0ceeaa1
Remove FilterBarView
kean 94809f0
Remove FilterChipButton
kean 4e976a9
Remove ActivityDetailViewController
kean f4fbc82
Activity Logs: Code Removal – Part 5 (#24608)
kean cbfbad3
Remove ActivityStore usages
kean 8420f31
Remove ActivityStoreTests
kean d77e1d4
Fix how isAwaitingCredentials works
kean c4c37d2
Remove ActivityStore
kean 55cfee4
Activity Logs: Code Removal – Part 6 (#24609)
kean 450d149
Integrate ActivityContentRouter and FormattableActivity
kean 9746eaf
Integrate ActivityContentRouter and FormattableActivity (#24610)
kean e45c028
Update filter icon
kean f491206
Update filters icon
kean b4ee7ea
Update icons for filters in DataViews (#24611)
kean c930476
Remove WPStyleGuide+Activity and fix an issue with ActivityFormattabl…
kean 0c04776
Fix layout of ActivityFormattableContentView
kean 4ab4e55
Add placeholders for empty fields
kean 7b3ccf9
Remove build instructions from CLAUDE.md
kean 348bfb4
Add more instructions for CLAUDE
kean 4fa01ef
Handle a scenario where logs are from existing user
kean 84ad407
Remove obsolete tests
kean 156d2a9
Update UI tests
kean 521ff21
Fix release build
kean e636424
Use Duration
kean 7bf0c14
Merge branch 'trunk' into logs-merge-test
kean 76ffd88
Simplify CardView
kean 10dde0e
Add TODO for iOS 17
kean b4a18ae
Move state change to onAppear
kean File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| { | ||
| "permissions": { | ||
| "allow": [ | ||
| "Bash(cat:*)", | ||
| "Bash(ls:*)", | ||
| "Bash(rg:*)", | ||
| "Bash(find:*)", | ||
| "Bash(grep:*)", | ||
| "Bash(head:*)", | ||
| "Bash(tail:*)", | ||
| "Bash(wc:*)", | ||
| "Bash(tree:*)", | ||
| "Bash(git:log,status,diff,branch)", | ||
| ], | ||
| "deny": [] | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| import SwiftUI | ||
|
|
||
| /// A reusable card view component that provides a consistent container style | ||
| /// with optional title and customizable content. | ||
| public struct CardView<Content: View>: View { | ||
| let title: String? | ||
| @ViewBuilder let content: () -> Content | ||
|
|
||
| public init(_ title: String? = nil, @ViewBuilder content: @escaping () -> Content) { | ||
| self.title = title | ||
| self.content = content | ||
| } | ||
|
|
||
| public var body: some View { | ||
| VStack(alignment: .leading, spacing: 16) { | ||
| if let title { | ||
| Text(title.uppercased()) | ||
| .font(.caption) | ||
| .foregroundStyle(.secondary) | ||
| } | ||
| content() | ||
| } | ||
| .frame(maxWidth: .infinity, alignment: .leading) | ||
| .padding() | ||
| .clipShape(RoundedRectangle(cornerRadius: 8)) | ||
| .overlay( | ||
| RoundedRectangle(cornerRadius: 8) | ||
| .stroke(Color(.separator), lineWidth: 0.5) | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| #Preview("With Title") { | ||
| CardView("Section Title") { | ||
| VStack(alignment: .leading, spacing: 12) { | ||
| Text("Card Content") | ||
| Text("More content here") | ||
| .foregroundStyle(.secondary) | ||
| } | ||
| } | ||
| .padding() | ||
| } | ||
|
|
||
| #Preview("Without Title") { | ||
| CardView { | ||
| HStack { | ||
| Image(systemName: "star.fill") | ||
| .foregroundStyle(.yellow) | ||
| Text("Featured Item") | ||
| Spacer() | ||
| } | ||
| } | ||
| .padding() | ||
| } | ||
35 changes: 35 additions & 0 deletions
35
Modules/Sources/WordPressUI/Views/DataView/DataViewPaginatedForEach.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import SwiftUI | ||
|
|
||
| /// A view that displays paginated data using ForEach with automatic loading triggers. | ||
| public struct DataViewPaginatedForEach<Response: DataViewPaginatedResponseProtocol, Content: View>: View { | ||
| @ObservedObject private var response: Response | ||
| private let content: (Response.Element) -> Content | ||
|
|
||
| /// Creates a paginated ForEach view. | ||
| /// | ||
| /// - Parameters: | ||
| /// - response: The paginated response handler that manages the data. | ||
| /// - content: A view builder that creates the content for each item. | ||
| public init( | ||
| response: Response, | ||
| @ViewBuilder content: @escaping (Response.Element) -> Content | ||
| ) { | ||
| self.response = response | ||
| self.content = content | ||
| } | ||
|
|
||
| public var body: some View { | ||
| ForEach(response.items) { item in | ||
| content(item) | ||
| .onAppear { | ||
| response.onRowAppeared(item) | ||
| } | ||
| } | ||
| if response.isLoading { | ||
| DataViewPagingFooterView(.loading) | ||
| } else if response.error != nil { | ||
| DataViewPagingFooterView(.failure) | ||
| .onRetry { response.loadMore() } | ||
| } | ||
| } | ||
| } |
122 changes: 122 additions & 0 deletions
122
Modules/Sources/WordPressUI/Views/DataView/DataViewPaginatedResponse.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| import Foundation | ||
| import SwiftUI | ||
|
|
||
| @MainActor | ||
| public protocol DataViewPaginatedResponseProtocol: ObservableObject { | ||
| associatedtype Element: Identifiable | ||
|
|
||
| var items: [Element] { get } | ||
| var isLoading: Bool { get } | ||
| var error: Error? { get } | ||
|
|
||
| func onRowAppeared(_ item: Element) | ||
| @discardableResult func loadMore() -> Task<Void, Error>? | ||
| } | ||
|
|
||
| /// A generic paginated response handler that manages loading items with flexible pagination. | ||
| /// This class is designed to be used in the UI in conjunction with `PaginatedForEach`. | ||
| @MainActor | ||
| public final class DataViewPaginatedResponse<Element: Identifiable, PageIndex>: DataViewPaginatedResponseProtocol { | ||
| @Published public private(set) var total: Int? | ||
| @Published public private(set) var items: [Element] = [] | ||
| @Published public private(set) var hasMore = true | ||
| @Published public private(set) var isLoading = false | ||
| @Published public private(set) var error: Error? | ||
|
|
||
| /// Result of a paginated load operation. | ||
| public struct Page { | ||
| public let items: [Element] | ||
| public let total: Int? | ||
| public let hasMore: Bool | ||
| public let nextPage: PageIndex? | ||
|
|
||
| public init(items: [Element], total: Int? = nil, hasMore: Bool, nextPage: PageIndex?) { | ||
| self.items = items | ||
| self.total = total | ||
| self.hasMore = hasMore | ||
| self.nextPage = nextPage | ||
| } | ||
| } | ||
|
|
||
| public var isEmpty: Bool { items.isEmpty } | ||
|
|
||
| private var nextPage: PageIndex? | ||
| private let loadPage: (PageIndex?) async throws -> Page | ||
|
|
||
| /// Creates a new paginated response handler. | ||
| /// | ||
| /// - Parameter loadPage: A closure that loads items using pagination. | ||
| /// - Parameter pageIndex: The page index to load (nil for initial load). | ||
| /// - Returns: A PaginatedResult containing the items, total count, whether more pages exist, and next page index. | ||
| /// - Throws: Any error from the initial page load. | ||
| public init(loadPage: @escaping (PageIndex?) async throws -> Page) async throws { | ||
| self.loadPage = loadPage | ||
|
|
||
| let response = try await loadPage(nil) | ||
| didLoad(response) | ||
| } | ||
|
|
||
| /// Loads the next page of items. | ||
| /// | ||
| /// This method will do nothing if: | ||
| /// - There are no more pages to load | ||
| /// - A page is currently being loaded | ||
| @discardableResult | ||
| public func loadMore() -> Task<Void, Error>? { | ||
| guard hasMore && !isLoading else { | ||
| return nil | ||
| } | ||
| error = nil | ||
| isLoading = true | ||
| return Task { | ||
| defer { isLoading = false } | ||
| do { | ||
| let response = try await loadPage(nextPage) | ||
| didLoad(response) | ||
| } catch { | ||
| self.error = error | ||
| throw error | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private func didLoad(_ response: Page) { | ||
| total = response.total | ||
| nextPage = response.nextPage | ||
| hasMore = response.hasMore | ||
|
|
||
| let existingIDs = Set(items.map(\.id)) | ||
| let newItems = response.items.filter { | ||
| !existingIDs.contains($0.id) | ||
| } | ||
| items += newItems | ||
| } | ||
|
|
||
| /// Triggers loading more items when a row appears. | ||
| /// | ||
| /// Call this method when a row becomes visible. If the row is within the last 10 items | ||
| /// and there's no current error, it will trigger loading the next page. | ||
| /// | ||
| /// - Parameter row: The row that appeared. | ||
| public func onRowAppeared(_ row: Element) { | ||
| guard items.suffix(10).contains(where: { $0.id == row.id }) else { | ||
| return | ||
| } | ||
| if error == nil { | ||
| loadMore() | ||
| } | ||
| } | ||
|
|
||
| /// Removes an item with the specified ID from the loaded items. | ||
| /// | ||
| /// - Parameter id: The ID of the item to remove. | ||
| public func deleteItem(withID id: Element.ID) { | ||
| guard let index = items.firstIndex(where: { $0.id == id }) else { | ||
| return | ||
| } | ||
| items.remove(at: index) | ||
| if let total { | ||
| self.total = total - 1 | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this
Groupnecessary? Does moving the.framecall toVStackand deleting thisGrouplook as expected?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it works the same – updated.