Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
d54dd5f
Bump API version
Xialtal May 4, 2026
84d1830
[WIP] TicketClient
Xialtal May 4, 2026
a60228d
Improve TicketInfo model
Xialtal May 4, 2026
9b39ba6
Improve TicketsList model
Xialtal May 4, 2026
750d59f
Add ticket endpoint to TicketClient
Xialtal May 4, 2026
0751847
Fix TicketParser
Xialtal May 4, 2026
7698fd8
Fix ticket status parsing
Xialtal May 5, 2026
b507496
[WIP] TicketFeature
Xialtal May 5, 2026
62cdfeb
[WIP] Tickets List
Xialtal May 8, 2026
ee58da0
Add yellow color to SharedUI
Xialtal May 8, 2026
afb7532
Add yellowAlpha color to SharedUI
Xialtal May 8, 2026
ffbe111
Add tickets pagination settings
Xialtal May 8, 2026
9aa16e9
[WIP] Tickets List
Xialtal May 8, 2026
3f5be8a
Add tickets to app navigation
Xialtal May 8, 2026
5908c75
Add tickets option to topic context menu
Xialtal May 8, 2026
a35cd0d
Add modify ticket comment endpoint
Xialtal May 8, 2026
56e11f7
Add processedAt field to TicketInfo model
Xialtal May 8, 2026
5aca3ce
Add change ticket status endpoint
Xialtal May 9, 2026
07f4024
Add PasteboardClient to TicketsListFeature dependencies
Xialtal May 9, 2026
674ea8f
Add CacheClient to TicketsListFeature dependencies
Xialtal May 10, 2026
7033a12
Improve tickets list endpoint
Xialtal May 10, 2026
21a385c
Add tickets settings to AppSettings model
Xialtal May 10, 2026
2dca8c3
[WIP] Tickets List
Xialtal May 10, 2026
bc7bcfd
Add user & ticket delegate handling for TicketsListFeature
Xialtal May 10, 2026
e6c607e
[WIP] Ticket Status History
Xialtal May 10, 2026
217cc87
Add ticket status history endpoint
Xialtal May 10, 2026
40fbd16
Improve ticket status change response parser
Xialtal May 10, 2026
90cabcd
Add TicketStatusHistory model
Xialtal May 10, 2026
273bd1c
Extract title for TicketStatus
Xialtal May 10, 2026
53a4f1d
[WIP] Ticket Status History
Xialtal May 10, 2026
b6ada78
Add status history to ticket context menu
Xialtal May 10, 2026
9e3862e
Add picker to ticket status badge on tap
Xialtal May 10, 2026
f9a1f85
Fix tickets list refreshing
Xialtal May 10, 2026
9f2e903
Add ticket opening on tap
Xialtal May 10, 2026
4585044
Remove send comment option from ticket context menu
Xialtal May 10, 2026
81d5f48
Merge remote-tracking branch 'origin/develop' into feature/moder-kit
Xialtal May 10, 2026
f80a046
[WIP] Ticket
Xialtal May 11, 2026
830b890
Merge remote-tracking branch 'origin/develop' into feature/moder-kit
Xialtal May 11, 2026
bfbe3c1
Fix ticket row background in dark mode
Xialtal May 11, 2026
d852815
Add Tickets to More tab
Xialtal May 11, 2026
3fd5119
Fix ticket status row background in dark mode
Xialtal May 12, 2026
b8f84dc
[WIP] Ticket
Xialtal May 12, 2026
0ad6df5
Fix missing dependencies
Xialtal May 12, 2026
388baf4
Update Package.resolved
Xialtal May 12, 2026
fe7b415
Fix sort type localization in tickets list
Xialtal May 12, 2026
97c872c
Fix ticket status crash in tickets list
Xialtal May 12, 2026
224de0d
Improve page changing on refreshing for tickets list
Xialtal May 12, 2026
9ac5227
Temp fix for ticket status picker
Xialtal May 12, 2026
355b532
Fix ticket parser
Xialtal May 12, 2026
b1cab10
Fix session username init for TicketFeature
Xialtal May 12, 2026
e4a7291
Fix perception warnings
Xialtal May 12, 2026
33e4481
Improve navigation title for TicketScreen
Xialtal May 12, 2026
b1201ca
Fix delegates handling for ticket
Xialtal May 12, 2026
c46e500
Fix ticket status history parser
Xialtal May 12, 2026
0c85e3c
Fix ticket status history parser
Xialtal May 12, 2026
138351b
Fix experimental navigation in tickets list
Xialtal May 13, 2026
fb44afa
Close ticket status history sheet on handler tap
Xialtal May 13, 2026
62dd330
Fix ticket status localization
Xialtal May 13, 2026
a6d245f
Fix perception warnings
Xialtal May 13, 2026
f01ee96
Add ticket comment delete endpoint
Xialtal May 13, 2026
5456a3c
Improve ticket toast
Xialtal May 13, 2026
25feaee
Add ticket comment delete option to context menu
Xialtal May 14, 2026
f0e17f4
Add refresh support for ticket
Xialtal May 14, 2026
891daee
Add edit ticket comment option to context menu
Xialtal May 14, 2026
7ec845c
Fix alert placeholder text localization
Xialtal May 14, 2026
c6d81a2
Add comment ticket button
Xialtal May 14, 2026
4cbf80c
TicketFeature improvements
Xialtal May 14, 2026
75d76e2
Clear ticket comment input field on error or success
Xialtal May 14, 2026
d8e070b
Bump API version
Xialtal May 14, 2026
68e16fd
Fix post karma history endpoint
Xialtal May 14, 2026
a3a981a
Add forum event log endpoint
Xialtal May 14, 2026
d59eb72
Fix post karma history row background in dark mode
Xialtal May 14, 2026
b8920d3
Improve reputation change actions
Xialtal May 14, 2026
c329996
Rework reputation vote context menu
Xialtal May 14, 2026
d755b99
Fix analytics for reputation vote context menu
Xialtal May 14, 2026
c60f000
Add auth check for reputation vote context menu
Xialtal May 14, 2026
464d714
Fix ticket status change
Xialtal May 14, 2026
03cb7f8
Add onNextAppear for tickets list
Xialtal May 14, 2026
2534713
Fix html symbols in ticket title
Xialtal May 14, 2026
860938a
Improve change ticket status toast for ru localization
Xialtal May 15, 2026
dc208f9
[WIP] Forum Event Log
Xialtal May 15, 2026
f32125d
[WIP] Forum Event Log
Xialtal May 15, 2026
8b29e8b
Add topic history to topic stat
Xialtal May 15, 2026
53f6bb1
Add history option to post context menu
Xialtal May 15, 2026
3e8dbd9
Fix context menu localization for forum event log
Xialtal May 15, 2026
9d03f66
Fix crash on open post/topic history
Xialtal May 15, 2026
f72ecba
Fix copy link in forum event log context menu
Xialtal May 15, 2026
a74eb01
Fix post open from context menu in forum event log
Xialtal May 15, 2026
269a900
Close forum stat sheet on topic history tap
Xialtal May 15, 2026
a71b7ba
Add tickets deeplinks support
Xialtal May 15, 2026
99b4b36
Add forum event log deeplink support
Xialtal May 15, 2026
f261cc3
Improve site search deeplink
Xialtal May 15, 2026
8b2772d
Fix initial offset in tickets list
Xialtal May 15, 2026
9309044
Improve comment edit text init
Xialtal May 15, 2026
f8b0ab2
Remove [na] tag from ticket comment content
Xialtal May 15, 2026
e1d7048
Add reputation vote modified badge
Xialtal May 15, 2026
232c2fd
Improve reputation localizable
Xialtal May 15, 2026
9cbbf26
Add change reputation option to profile context menu
Xialtal May 16, 2026
8cef526
Fix vote label & symbol in ReputationVote model
Xialtal May 16, 2026
5b9d3ce
Fix vote colors in reputation
Xialtal May 16, 2026
7693506
Add modify reputation endpoint
Xialtal May 16, 2026
a47e6f8
Add delete/restore option to reputation context menu
Xialtal May 16, 2026
6d50eed
Improve ReputationChangeRequest model
Xialtal May 16, 2026
cbefc67
Rework delegate for ForumMoveFeature
Xialtal May 16, 2026
567cd88
Add success toast after moving post
Xialtal May 16, 2026
1a2024c
Add success toast after moving topic
Xialtal May 16, 2026
beed958
Move ticket comment content from BBBuilder to TopicBuilder
Xialtal May 16, 2026
4e35e27
Improve ForumJump model
Xialtal May 17, 2026
bc3d701
Add posts filter support for topic deeplinks
Xialtal May 17, 2026
2e6145d
Add show all posts in topic by default to AppSettings
Xialtal May 17, 2026
c393936
Merge branch 'develop' into feature/moder-kit
SubvertDev May 17, 2026
ef639c9
Improve ReputationParser
Xialtal May 17, 2026
1cf775c
Merge branch 'develop' into feature/moder-kit
SubvertDev May 17, 2026
15e1170
Merge branch 'develop' into feature/moder-kit
SubvertDev May 17, 2026
4c01f06
Add show all posts in topic option to settings
Xialtal May 17, 2026
c012dbd
Bump API version
Xialtal May 17, 2026
a06c5df
Fix posts filter for jump forum endpoint
Xialtal May 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions Modules/Sources/APIClient/APIClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public struct APIClient: Sendable {
public var editUserProfile: @Sendable (_ request: UserProfileEditRequest) async throws -> Bool
public var addUserNote: @Sendable (_ userId: Int, _ content: String) async throws -> UserNoteResponse
public var getReputationVotes: @Sendable (_ data: ReputationVotesRequest) async throws -> ReputationVotes
public var modifyReputation: @Sendable (_ id: Int, _ type: ReputationModifyActionType) async throws -> Bool
public var changeReputation: @Sendable (_ data: ReputationChangeRequest) async throws -> ReputationChangeResponseType
public var updateUserAvatar: @Sendable (_ userId: Int, _ image: Data) async throws -> UserAvatarResponseType
public var updateUserDevice: @Sendable (_ userId: Int, _ action: UserDeviceAction, _ fullTag: String, _ isPrimary: Bool) async throws -> Bool
Expand All @@ -59,6 +60,7 @@ public struct APIClient: Sendable {
public var getForumsList: @Sendable (_ policy: CachePolicy) async throws -> AsyncThrowingStream<[ForumInfo], any Error>
public var getForum: @Sendable (_ id: Int, _ page: Int, _ perPage: Int, _ policy: CachePolicy) async throws -> AsyncThrowingStream<Forum, any Error>
public var getForumStat: @Sendable (_ id: Int) async throws -> ForumStat
public var getForumEventLog: @Sendable (_ id: Int, _ type: ForumEventLogType) async throws -> [ForumEventLog]
public var jumpForum: @Sendable (_ request: JumpForumRequest) async throws -> ForumJump
public var markRead: @Sendable (_ id: Int, _ isTopic: Bool) async throws -> Bool
public var getAnnouncement: @Sendable (_ id: Int) async throws -> Announcement
Expand Down Expand Up @@ -259,6 +261,17 @@ extension APIClient: DependencyKey {
return try await parser.parseReputationVotes(response)
},

modifyReputation: { id, type in
let command = MemberCommand.reputation(data: MemberReputationRequest(
memberId: 0,
action: type.transferType,
postId: id,
reason: ""
))
let response = try await api.send(command)
let status = Int(response.getResponseStatus())!
return status == 0
},
changeReputation: { request in
let command = MemberCommand.reputation(data: MemberReputationRequest(
memberId: request.userId,
Expand Down Expand Up @@ -332,11 +345,17 @@ extension APIClient: DependencyKey {
return try await parser.parseForumStat(response)
},

getForumEventLog: { id, type in
let command = ForumCommand.eventLog(type: type.rawValue, id: id)
let response = try await api.send(command)
return try await parser.parseForumEventLog(response)
},

jumpForum: { request in
let command = ForumCommand.jump(data: ForumJumpRequest(
type: request.transferType,
postId: request.postId,
allPosts: request.allPosts,
postsFilter: request.postsFilter.rawValue,
topicId: request.topicId
))
let response = try await api.send(command)
Expand Down Expand Up @@ -504,7 +523,7 @@ extension APIClient: DependencyKey {
return status == 0
},
postKarmaHistory: { postId in
let command = ForumCommand.Post.history(id: postId)
let command = ForumCommand.Post.karma(postId: postId, action: .history)
let response = try await api.send(command)
return try await parser.parsePostKarmaHistory(response)
},
Expand Down Expand Up @@ -720,6 +739,9 @@ extension APIClient: DependencyKey {
getReputationVotes: { _ in
return .mock
},
modifyReputation: { _, _ in
return true
},
changeReputation: { _ in
return .success
},
Expand All @@ -743,6 +765,12 @@ extension APIClient: DependencyKey {
getForumStat: { _ in
return .mock
},
getForumEventLog: { _, type in
switch type {
case .post: return .mockPost
case .topic: return .mockTopic
}
},
jumpForum: { _ in
return .mock
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// ReputationModifyActionType+Extension.swift
// ForPDA
//
// Created by Xialtal on 16.05.26.
//

import PDAPI
import Models

extension ReputationModifyActionType {
nonisolated var transferType: MemberReputationRequest.ActionType {
switch self {
case .delete: .delete
case .restore: .restore
}
}
}
7 changes: 4 additions & 3 deletions Modules/Sources/APIClient/Requests/JumpForumRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@

import Foundation
import PDAPI
import Models

public struct JumpForumRequest {
public let postId: Int
public let topicId: Int
public let allPosts: Bool
public let postsFilter: TopicPostsFilter
public let type: ForumJumpType

nonisolated public var transferType: ForumJumpRequest.JumpType {
Expand All @@ -25,12 +26,12 @@ public struct JumpForumRequest {
public init(
postId: Int,
topicId: Int,
allPosts: Bool,
postsFilter: TopicPostsFilter,
type: ForumJumpType
) {
self.postId = postId
self.topicId = topicId
self.allPosts = allPosts
self.postsFilter = postsFilter
self.type = type
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,12 @@ public struct ReputationChangeRequest: Sendable {
public enum ChangeActionType: Sendable {
case up
case down
case delete
case recover
}

nonisolated var transferVoteType: MemberReputationRequest.ActionType {
switch action {
case .up: .plus
case .down: .minus

// TODO: Implement.
case .delete, .recover: .plus
}
}

Expand Down
8 changes: 7 additions & 1 deletion Modules/Sources/AnalyticsClient/Events/ReputationEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public enum ReputationEvent: Event {
case sourceTopicTapped(Int)
case sourceArticleTapped(Int)

case voteMenuGoToAuthorTapped(Int)
case voteMenuComplainTapped(Int)

public var name: String {
return "Reputation " + eventName(for: self).inProperCase
}
Expand All @@ -26,9 +29,12 @@ public enum ReputationEvent: Event {
case let .profileTapped(profileId):
return ["profileId": String(profileId)]

case let .complainTapped(voteId):
case let .voteMenuComplainTapped(voteId):
return ["voteId": String(voteId)]

case let .voteMenuGoToAuthorTapped(profileId):
return ["profileId": String(profileId)]

case let .sourceProfileTapped(profileId):
return ["profileId": String(profileId)]

Expand Down
13 changes: 11 additions & 2 deletions Modules/Sources/AppFeature/AppFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ import CacheClient
import DeviceSpecificationsFeature
import DeviceTypeFeature
import MoreFeature
import TicketsListFeature
import TicketFeature
import ForumEventLogFeature

@Reducer
public struct AppFeature: Reducer, Sendable {
Expand Down Expand Up @@ -588,10 +591,16 @@ public struct AppFeature: Reducer, Sendable {
case .device(let tag, let subTag):
.devDB(.specifications(DeviceSpecificationsFeature.State(tag: tag, subTag: subTag)))
}
case let .topic(id, goTo):
screen = .forum(.topic(TopicFeature.State(topicId: id!, goTo: goTo)))
case let .ticketsList(offset):
screen = .tickets(.ticketsList(TicketsListFeature.State(type: .list, initialOffset: offset)))
case let .ticket(id):
screen = .tickets(.ticket(TicketFeature.State(id: id)))
case let .topic(id, goTo, filter):
screen = .forum(.topic(TopicFeature.State(topicId: id!, goTo: goTo, postsFilter: filter)))
case let .forum(id, page):
screen = .forum(.forum(ForumFeature.State(forumId: id, initialPage: page)))
case let .eventLog(id, type):
screen = .forum(.eventLog(ForumEventLogFeature.State(id: id, type: type)))
case let .user(id):
screen = .more(.profile(ProfileFeature.State(userId: id)))
case let .qms(id: id):
Expand Down
8 changes: 8 additions & 0 deletions Modules/Sources/AppFeature/AppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,14 @@ extension LiquidTabView {
return nil
}

case let .tickets(path):
switch path.case {
case let .ticketsList(store):
return store.scope(state: \.pageNavigation, action: \.pageNavigation)
default:
return nil
}

default:
return nil
}
Expand Down
29 changes: 29 additions & 0 deletions Modules/Sources/AppFeature/Navigation/Path.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import DeviceSpecificationsFeature
import DeviceTypeFeature
import FavoritesRootFeature
import FavoritesFeature
import ForumEventLogFeature
import ForumFeature
import ForumsListFeature
import HistoryFeature
Expand All @@ -27,6 +28,8 @@ import ReputationFeature
import SearchFeature
import SearchResultFeature
import SettingsFeature
import TicketFeature
import TicketsListFeature
import TopicFeature
import AuthFeature
import MoreFeature
Expand All @@ -37,6 +40,7 @@ public enum Path {
case devDB(DevDB.Body = DevDB.body)
case favorites(FavoritesFeature)
case forum(Forum.Body = Forum.body)
case tickets(Tickets.Body = Tickets.body)
case more(More.Body = More.body)
case settings(Settings.Body = Settings.body)
case search(Search.Body = Search.body)
Expand Down Expand Up @@ -70,6 +74,13 @@ public enum Path {
case forum(ForumFeature)
case announcement(AnnouncementFeature)
case topic(TopicFeature)
case eventLog(ForumEventLogFeature)
}

@Reducer
public enum Tickets {
case ticketsList(TicketsListFeature)
case ticket(TicketFeature)
}

@Reducer
Expand Down Expand Up @@ -98,6 +109,7 @@ extension Path.Articles.State: Equatable {}
extension Path.DevDB.State: Equatable {}
extension Path.More.State: Equatable {}
extension Path.Forum.State: Equatable {}
extension Path.Tickets.State: Equatable {}
extension Path.Settings.State: Equatable {}
extension Path.Search.State: Equatable {}
extension Path.QMS.State: Equatable {}
Expand All @@ -122,6 +134,9 @@ extension Path {
case let .forum(path):
ForumViews(path)

case let .tickets(path):
TicketsViews(path)

case let .settings(path):
SettingsViews(path)

Expand Down Expand Up @@ -203,12 +218,26 @@ extension Path {
TopicScreen(store: store)
.tracking(for: TopicScreen.self, ["id": store.topicId])

case let .eventLog(store):
ForumEventLogScreen(store: store)

case let .announcement(store):
AnnouncementScreen(store: store)
.tracking(for: AnnouncementScreen.self, ["id": store.announcementId])
}
}

@MainActor @ViewBuilder
private static func TicketsViews(_ store: Store<Path.Tickets.State, Path.Tickets.Action>) -> some View {
switch store.case {
case let .ticketsList(store):
TicketsListScreen(store: store)

case let .ticket(store):
TicketScreen(store: store)
}
}

@MainActor @ViewBuilder
private static func SettingsViews(_ store: Store<Path.Settings.State, Path.Settings.Action>) -> some View {
switch store.case {
Expand Down
Loading