Remove unused code

This commit is contained in:
Jacek Krasiukianis
2025-02-11 18:41:18 +00:00
parent b50731d498
commit f35b3844e3
33 changed files with 43 additions and 343 deletions
@@ -1,51 +0,0 @@
// Copyright (c) 2024 Proton Technologies AG
//
// This file is part of Proton Mail.
//
// Proton Mail is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import InboxDesignSystem
import proton_app_uniffi
import class SwiftUI.UIImage
struct CustomFolderNode: Sendable {
var folder: PMCustomFolder
var children: [CustomFolderNode]
/**
Flattens the folder structure.
- Returns: An array of flattened CustomFolders where the parent folder is followed by its child folders
Runs a tree traversal that follows the Root-Left-Right policy where:
1. The root node of the subtree is visited first.
2. Then the left subtree is traversed.
3. At last, the right subtree is traversed.
Example:
the following structure
```
F1
|- F11
|- F111
|- F112
|- F12
```
would return [F1, F11, F111, F112, F12]
*/
func preorderTreeTraversal() -> [CustomFolderNode] {
return [self] + children.flatMap { $0.preorderTreeTraversal() }
}
}
@@ -15,7 +15,6 @@
// You should have received a copy of the GNU General Public License
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import InboxDesignSystem
import SwiftUI
enum PreviewData {
@@ -94,5 +94,4 @@ extension EventLoopService: ApplicationServiceDidEnterBackground {
protocol EventLoopProvider: AnyObject {
func pollEvents()
func pollEventsAsync() async
}
@@ -55,10 +55,6 @@ final class MailboxModel: ObservableObject {
@NestedObservableObject var accountManagerCoordinator: AccountManagerCoordinator
var userSession: MailUserSession {
dependencies.appContext.userSession
}
var viewMode: ViewMode {
mailbox?.viewMode() ?? .conversations
}
@@ -21,16 +21,12 @@ import proton_app_uniffi
import SwiftUI
final class EventLoopErrorCoordinator: Sendable, ObservableObject {
private let userSession: MailUserSession
private let toastStateStore: ToastStateStore
private let handle: EventLoopErrorObserverHandle
private let eventLoopErrorCallback: EventLoopErrorCallbackWrapper = .init()
init(userSession: MailUserSession, toastStateStore: ToastStateStore) {
self.userSession = userSession
self.toastStateStore = toastStateStore
self.handle = userSession.observeEventLoopErrors(callback: eventLoopErrorCallback)
eventLoopErrorCallback.delegate = { [weak self] error in
eventLoopErrorCallback.delegate = { error in
AppLogger.log(error: error)
let toast = Toast(
title: nil,
@@ -39,7 +35,7 @@ final class EventLoopErrorCoordinator: Sendable, ObservableObject {
style: .error,
duration: 10
)
self?.toastStateStore.present(toast: toast)
toastStateStore.present(toast: toast)
}
}
@@ -20,13 +20,11 @@ import Foundation
import proton_app_uniffi
final class SendResultCoordinator: ObservableObject {
private let sendResultPublisher: SendResultPublisher
private var anyCancellables = Set<AnyCancellable>()
let presenter: SendResultPresenter
init(sendResultPublisher: SendResultPublisher, presenter: SendResultPresenter) {
self.sendResultPublisher = sendResultPublisher
self.presenter = presenter
sendResultPublisher
@@ -33,11 +33,7 @@ struct AvailableActionsProvider {
}
}
protocol AvailableActionsConvertible {
var availableActions: AvailableActions { get }
}
extension MessageAvailableActions: AvailableActionsConvertible {
extension MessageAvailableActions {
var availableActions: AvailableActions {
.init(
@@ -50,7 +46,7 @@ extension MessageAvailableActions: AvailableActionsConvertible {
}
extension ConversationAvailableActions: AvailableActionsConvertible {
extension ConversationAvailableActions {
var availableActions: AvailableActions {
.init(
@@ -36,7 +36,6 @@ struct MessageActionButtonsView: View {
}
private struct MessageActionButtonView: View {
@EnvironmentObject var toastStateStore: ToastStateStore
let image: ImageResource
let text: LocalizedStringResource
var onButtonTap: () -> Void
@@ -17,7 +17,6 @@
import AccountLogin
import Combine
import InboxComposer
import InboxCoreUI
import proton_app_uniffi
import SwiftUI
@@ -16,7 +16,6 @@
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import AccountManager
import InboxComposer
import InboxCore
import InboxCoreUI
import InboxDesignSystem
@@ -15,7 +15,6 @@
// You should have received a copy of the GNU General Public License
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import InboxDesignSystem
import proton_app_uniffi
import SwiftUI
@@ -40,7 +40,7 @@ enum SidebarItem: Equatable, Identifiable {
switch self {
case .system, .label, .folder:
true
case .other(let item):
case .other:
false
}
}
@@ -16,7 +16,6 @@
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import Combine
import InboxCore
class EmailsPrefetchingNotifier: ApplicationServiceDidBecomeActive, @unchecked Sendable {
@@ -1,58 +0,0 @@
// Copyright (c) 2024 Proton Technologies AG
//
// This file is part of Proton Mail.
//
// Proton Mail is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
@testable import ProtonMail
import InboxTesting
import proton_app_uniffi
import XCTest
final class CustomFolderNodeTests: BaseTestCase {
func testPreorderTreeTraversal_whenSingleFolder_itReturnsTheFolder() {
let name = "Folder"
let sut = CustomFolderNode(folder: .testData(name: name), children: [])
let result = sut.preorderTreeTraversal()
XCTAssertEqual(result.count, 1)
XCTAssertEqual(result[0].folder.name, name)
}
func testPreorderTreeTraversal_whenNestedFolders_itReturnsTheFlattenedArray() {
let sut = CustomFolderNode(
folder: .testData(name: "F1"),
children: [
CustomFolderNode(
folder: .testData(name: "F11"),
children: [
CustomFolderNode(folder: .testData(name: "F111"), children: []),
CustomFolderNode(folder: .testData(name: "F112"), children: [])
]
),
CustomFolderNode(folder: .testData(name: "F12"), children: []),
CustomFolderNode(folder: .testData(name: "F13"), children: [
CustomFolderNode(folder: .testData(name: "F131"), children: []),
])
]
)
let result = sut.preorderTreeTraversal()
XCTAssertEqual(result.count, 7)
XCTAssertEqual(result.map(\.folder.name), ["F1", "F11", "F111", "F112", "F12", "F13", "F131"])
}
}
@@ -35,7 +35,6 @@ public struct ComposerScreen: View {
wrappedValue:
ComposerScreenModel(
messageId: messageId,
contactProvider: dependencies.contactProvider,
userSession: dependencies.userSession
)
)
@@ -53,7 +52,6 @@ public struct ComposerScreen: View {
wrappedValue: ComposerScreenModel(
draft: draft,
draftOrigin: draftOrigin,
contactProvider: dependencies.contactProvider,
userSession: dependencies.userSession
)
)
@@ -16,7 +16,6 @@
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import InboxCore
import InboxCoreUI
import proton_app_uniffi
import SwiftUI
@@ -26,17 +25,13 @@ final class ComposerScreenModel: ObservableObject {
private var isCancelled: Bool = false
let pendingQueueProvider: PendingQueueProvider
init(
messageId: ID,
contactProvider: ComposerContactProvider,
userSession: MailUserSession
) {
init(messageId: ID, userSession: MailUserSession) {
self.state = .loadingDraft
self.pendingQueueProvider = .init(userSession: userSession)
openDraftMessage(session: userSession, messageId: messageId)
}
init(draft: AppDraftProtocol, draftOrigin: DraftOrigin, contactProvider: ComposerContactProvider, userSession: MailUserSession) {
init(draft: AppDraftProtocol, draftOrigin: DraftOrigin, userSession: MailUserSession) {
self.pendingQueueProvider = .init(userSession: userSession)
self.state = .draftLoaded(draft: draft, draftOrigin: draftOrigin)
}
@@ -1,54 +0,0 @@
// Copyright (c) 2024 Proton Technologies AG
//
// This file is part of Proton Mail.
//
// Proton Mail is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import Foundation
enum ComposerScreenPreviewProvider {
static func makeRandom(suffix: String) -> RecipientUIModel {
switch [RecipientType.single, .single, .single, .group].randomElement()! {
case .single: return makeRandomSingleRecipient(suffix: suffix)
case .group: return makeRandomGroup(suffix: suffix)
}
}
static func makeRandomSingleRecipient(suffix: String) -> RecipientUIModel {
let address = ["john.doe_\(suffix)@apple.com", "laura.stern_\(suffix)@gmail.com", "mike2318.smith12398\(suffix)@protonmail.com", "anna\(suffix)@pm.me", "Hillary Scott <hey_hs_\(suffix)@gmail.com>", "Brandon <brandon_234\(suffix)@proton.me>", "andy_\(suffix)@proton.ch"].randomElement()!
return RecipientUIModel(
composerRecipient: .single(
.init(
displayName: "",
address: address,
validState: .valid
)
)
)
}
static func makeRandomGroup(suffix: String) -> RecipientUIModel {
return RecipientUIModel(
composerRecipient: .group(
.init(
displayName: ["Family_\(suffix)", "Gym_\(suffix) 🏋️‍♂️", "Football team with work colleagues \(suffix)", "🏖️ college trip \(suffix)"].randomElement()!,
recipients: [],
totalContactsInGroup: 0
)
)
)
}
}
@@ -63,7 +63,6 @@ public extension ComposerContactProvider {
static func productionInstance(session: MailUserSession) -> ComposerContactProvider {
let protonContactsProvider = ComposerProtonContactsDatasource(
mailUserSession: session,
repository: .productionInstance(mailUserSession: session)
)
return .init(protonContactsDatasource: protonContactsProvider)
@@ -16,7 +16,6 @@
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import InboxContacts
import InboxCore
import InboxCoreUI
import proton_app_uniffi
import UIKit
@@ -28,7 +27,6 @@ struct ComposerContactsResult {
}
struct ComposerProtonContactsDatasource: ComposerContactsDatasource {
let mailUserSession: MailUserSession
let repository: ContactSuggestionsRepository
func allContacts() async -> ComposerContactsResult {
@@ -108,12 +108,8 @@ final class RecipientsFieldController: UIViewController {
private func onIdleControllerTap() {
onEvent?(.onFieldTap)
}
private func updateView(for state: RecipientFieldState) {
updateView(for: state, noCellSelected: true)
}
private func updateView(for state: RecipientFieldState, noCellSelected: Bool) {
private func updateView(for state: RecipientFieldState) {
DispatchQueue.main.async { [weak self] in
guard let self else { return }
idleController.view.isHidden = state.controllerState == .editing
@@ -122,7 +122,6 @@ extension ContactPickerCell {
private final class LabelsView: UIView {
private let stack = SubviewFactory.stack
private let icon = SubviewFactory.icon
private let title = SubviewFactory.titleLabel
private let subtitle = SubviewFactory.subtitleLabel
@@ -159,12 +158,6 @@ private final class LabelsView: UIView {
private extension LabelsView {
private enum SubviewFactory {
static var icon: UIImageView {
let view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}
static var titleLabel: UILabel {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
@@ -154,12 +154,6 @@ extension ContactPickerController {
ComposerSubviewFactory.fieldTitle
}
static var textField: CursorTextField {
let view = CursorTextField()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}
static var tableView: UITableView {
let view = UITableView(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
@@ -34,12 +34,6 @@ final class SubjectFieldView: UIView {
set { textField.text = newValue }
}
var delegate: UITextFieldDelegate? {
didSet {
textField.delegate = delegate
}
}
init() {
super.init(frame: .zero)
translatesAutoresizingMaskIntoConstraints = false
@@ -15,7 +15,6 @@
// You should have received a copy of the GNU General Public License
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import InboxCore
import InboxDesignSystem
import SwiftUI
@@ -26,7 +26,7 @@ struct ComposerView: View {
@EnvironmentObject var toastStateStore: ToastStateStore
@StateObject private var model: ComposerModel
public init(
init(
draft: AppDraftProtocol,
draftOrigin: DraftOrigin,
contactProvider: ComposerContactProvider,
@@ -255,29 +255,6 @@
"Undo" : {
"comment" : "Undo action after message has been sent."
},
"Unrecognized MIME type" : {
"comment" : "Error when saving a draft",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Unrecognized MIME type"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Type MIME non reconnu"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Niet-herkend MIME-type"
}
}
}
},
"You're currently offline. This draft may not be up-to-date." : {
"comment" : "Draft might not be up-to-date when loaded"
}
@@ -90,12 +90,6 @@ enum L10n {
}
enum ComposerError {
static let unknownMimeType = LocalizedStringResource(
"Unrecognized MIME type",
bundle: .atURL(Bundle.module.bundleURL),
comment: "Error when saving a draft"
)
static func duplicateRecipient(address: String) -> LocalizedStringResource {
LocalizedStringResource(
"Removed duplicate recipient: \(address)",
@@ -29,7 +29,6 @@ final class ComposerProtonContactsDatasourceTests: XCTestCase {
override func setUp() {
super.setUp()
sut = ComposerProtonContactsDatasource(
mailUserSession: .empty(),
repository: .init(
permissionsHandler: CNContactStorePartialStub.self,
contactStore: CNContactStorePartialStub(),
@@ -50,13 +50,6 @@ public struct ContactSuggestionsRepository {
return await allContacts(deviceContacts)
}
func allContacts(query: String, completion: @escaping (ContactSuggestionsProtocol?) -> Void) {
Task {
let suggestions = await allContacts()
completion(suggestions)
}
}
// MARK: - Private
private func deviceContacts() -> [DeviceContact] {
@@ -17,10 +17,7 @@
import SwiftUI
public protocol Routable: Hashable, Identifiable {
associatedtype ViewType: View
func view() -> ViewType
protocol Routable: Hashable, Identifiable {
}
extension Routable {
@@ -21,7 +21,7 @@ struct GroupedContactsRepository {
private let mailUserSession: MailUserSession
private let contactsProvider: GroupedContactsProvider
public init(mailUserSession: MailUserSession, contactsProvider: GroupedContactsProvider) {
init(mailUserSession: MailUserSession, contactsProvider: GroupedContactsProvider) {
self.mailUserSession = mailUserSession
self.contactsProvider = contactsProvider
}
@@ -1,30 +0,0 @@
// Copyright (c) 2024 Proton Technologies AG
//
// This file is part of Proton Mail.
//
// Proton Mail is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail. If not, see https://www.gnu.org/licenses/.
import UIKit
protocol Reusable {
static var reuseIdentifier: String { get }
}
extension Reusable where Self: UIView {
static var reuseIdentifier: String {
String(describing: self)
}
}
@@ -54,29 +54,29 @@ final class ContactSuggestionsRepositoryTests: BaseTestCase {
super.tearDown()
}
func testAllContacts_WhenPermissionsDenied_ItDoesNotRequestForDeviceContacts() throws {
func testAllContacts_WhenPermissionsDenied_ItDoesNotRequestForDeviceContacts() async {
CNContactStoreSpy.stubbedAuthorizationStatus = [.contacts: .denied]
sut.allContacts(query: .empty, completion: { _ in })
_ = await sut.allContacts()
XCTAssertEqual(contactStoreSpy.enumerateContactsCalls.count, 0)
}
func testAllContacts_WhenPermissionsRestricted_ItDoesNotRequestForDeviceContacts() throws {
func testAllContacts_WhenPermissionsRestricted_ItDoesNotRequestForDeviceContacts() async {
CNContactStoreSpy.stubbedAuthorizationStatus = [.contacts: .restricted]
sut.allContacts(query: .empty, completion: { _ in })
_ = await sut.allContacts()
XCTAssertEqual(contactStoreSpy.enumerateContactsCalls.count, 0)
}
// MARK: - Permissions granted
func testAllContacts_WhenPermissionsGranted_ItRequestForDeviceContacts() throws {
func testAllContacts_WhenPermissionsGranted_ItRequestForDeviceContacts() async {
CNContactStoreSpy.stubbedAuthorizationStatus = [.contacts: .authorized]
sut.allContacts(query: .empty, completion: { _ in })
_ = await sut.allContacts()
XCTAssertEqual(contactStoreSpy.enumerateContactsCalls.count, 1)
XCTAssertEqual(contactStoreSpy.enumerateContactsCalls.last?.keysToFetch.count, 3)
XCTAssertEqual(contactStoreSpy.enumerateContactsCalls.last?.keysToFetch.map(\.description), [
@@ -86,16 +86,16 @@ final class ContactSuggestionsRepositoryTests: BaseTestCase {
])
}
func testAllContacts_WhenPermissionsGranted_ItRequestsForAllContactsWithDeviceContacts() throws {
func testAllContacts_WhenPermissionsGranted_ItRequestsForAllContactsWithDeviceContacts() async {
CNContactStoreSpy.stubbedAuthorizationStatus = [.contacts: .authorized]
contactStoreSpy.stubbedEnumerateContacts = [
.jonathanHorotvitz,
.travisHulkenberg
]
sut.allContacts(query: .empty, completion: { _ in })
_ = await sut.allContacts()
XCTAssertEqual(allContactsCalls.count, 1)
XCTAssertEqual(allContactsCalls.last, [
.init(
@@ -111,7 +111,7 @@ final class ContactSuggestionsRepositoryTests: BaseTestCase {
])
}
func testAllContacts_WhenPermissionsGranted_ItReturnsDeviceAndProtonContacts() throws {
func testAllContacts_WhenPermissionsGranted_ItReturnsDeviceAndProtonContacts() async {
CNContactStoreSpy.stubbedAuthorizationStatus = [.contacts: .authorized]
contactStoreSpy.stubbedEnumerateContacts = [
@@ -128,15 +128,9 @@ final class ContactSuggestionsRepositoryTests: BaseTestCase {
.deviceTravisHulkenberg,
.deviceMarcus
]
var receivedContacts: [ContactSuggestion] = []
sut.allContacts(query: .empty, completion: { result in
if let result {
receivedContacts = result.all()
}
})
let receivedContacts = await sut.allContacts()?.all() ?? []
XCTAssertEqual(receivedContacts.count, 6)
XCTAssertEqual(receivedContacts, [
.group(.businessGroup),
@@ -150,24 +144,24 @@ final class ContactSuggestionsRepositoryTests: BaseTestCase {
// MARK: - Permissions not granted
func testAllContacts_WhenPermissionsNotGranted_ItDoesNotRequestForDeviceContacts() throws {
func testAllContacts_WhenPermissionsNotGranted_ItDoesNotRequestForDeviceContacts() async {
CNContactStoreSpy.stubbedAuthorizationStatus = [.contacts: .denied]
sut.allContacts(query: .empty, completion: { _ in })
_ = await sut.allContacts()
XCTAssertEqual(contactStoreSpy.enumerateContactsCalls.count, 0)
}
func testAllContacts_WhenPermissionsNotGranted_ItRequestForAllContactsWithoutDeviceContacts() throws {
func testAllContacts_WhenPermissionsNotGranted_ItRequestForAllContactsWithoutDeviceContacts() async {
CNContactStoreSpy.stubbedAuthorizationStatus = [.contacts: .denied]
contactStoreSpy.stubbedEnumerateContacts = [
.jonathanHorotvitz,
.travisHulkenberg
]
sut.allContacts(query: "Ab", completion: { _ in })
_ = await sut.allContacts()
stubbedAllContacts = [
.group(.businessGroup),
.protonJohn,
@@ -180,7 +174,7 @@ final class ContactSuggestionsRepositoryTests: BaseTestCase {
XCTAssertEqual(allContactsCalls.last, [])
}
func testAllContacts_WhenPermissionsNotGranted_ItReturnsProtonContactsOnly() throws {
func testAllContacts_WhenPermissionsNotGranted_ItReturnsProtonContactsOnly() async {
CNContactStoreSpy.stubbedAuthorizationStatus = [.contacts: .denied]
contactStoreSpy.stubbedEnumerateContacts = [
@@ -192,15 +186,9 @@ final class ContactSuggestionsRepositoryTests: BaseTestCase {
.protonJohn,
.protonMark
]
var receivedContacts: [ContactSuggestion] = []
sut.allContacts(query: .empty, completion: { result in
if let result {
receivedContacts = result.all()
}
})
let receivedContacts = await sut.allContacts()?.all() ?? []
XCTAssertEqual(receivedContacts.count, 2)
XCTAssertEqual(receivedContacts, [
.protonJohn,