Skip to content

Commit

Permalink
Add new changelog design
Browse files Browse the repository at this point in the history
  • Loading branch information
mojganii committed Jan 15, 2025
1 parent 7fdaade commit cbca8a7
Show file tree
Hide file tree
Showing 16 changed files with 286 additions and 161 deletions.
20 changes: 16 additions & 4 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,7 @@
F041BE532C9878B60083EC28 /* ConnectionConfigurationBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F041BE522C9878B60083EC28 /* ConnectionConfigurationBuilder.swift */; };
F04413612BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04413602BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift */; };
F04413622BA45CE30018A6EE /* CustomListLocationNodeBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04413602BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift */; };
F048BFA22D31843000251CB9 /* ChangeLogModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F048BFA12D31842B00251CB9 /* ChangeLogModel.swift */; };
F04AF92D2C466013004A8314 /* EphemeralPeerNegotiationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04AF92C2C466013004A8314 /* EphemeralPeerNegotiationState.swift */; };
F04FBE612A8379EE009278D7 /* AppPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04FBE602A8379EE009278D7 /* AppPreferences.swift */; };
F050AE4E2B70D7F8003F4EDB /* LocationCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F050AE4D2B70D7F8003F4EDB /* LocationCellViewModel.swift */; };
Expand Down Expand Up @@ -976,6 +977,9 @@
F09A297C2A9F8A9B00EA3B6F /* VoucherTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = F09A29792A9F8A9B00EA3B6F /* VoucherTextField.swift */; };
F09A297D2A9F8A9B00EA3B6F /* RedeemVoucherContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F09A297A2A9F8A9B00EA3B6F /* RedeemVoucherContentView.swift */; };
F09A29822A9F8AD200EA3B6F /* RedeemVoucherInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F09A297F2A9F8AD200EA3B6F /* RedeemVoucherInteractor.swift */; };
F09C97212D311D8800ADE747 /* ChangeLogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F09C97202D311D7A00ADE747 /* ChangeLogView.swift */; };
F09C97232D3122F300ADE747 /* ChangeLogReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F09C97222D3122E400ADE747 /* ChangeLogReader.swift */; };
F09C97252D312ED000ADE747 /* BulletPointText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F09C97242D312ECD00ADE747 /* BulletPointText.swift */; };
F09D04B32AE919AC003D4F89 /* OutgoingConnectionProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F09D04AF2AE7F83D003D4F89 /* OutgoingConnectionProxy.swift */; };
F09D04B52AE93CB6003D4F89 /* OutgoingConnectionProxy+Stub.swift in Sources */ = {isa = PBXBuildFile; fileRef = F09D04B42AE93CB6003D4F89 /* OutgoingConnectionProxy+Stub.swift */; };
F09D04B72AE941DA003D4F89 /* OutgoingConnectionProxyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F09D04B62AE941DA003D4F89 /* OutgoingConnectionProxyTests.swift */; };
Expand Down Expand Up @@ -1052,7 +1056,6 @@
F0E8E4C32A602E0D00ED26A3 /* AccountDeletionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E8E4C22A602E0D00ED26A3 /* AccountDeletionViewModel.swift */; };
F0E8E4C52A60499100ED26A3 /* AccountDeletionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E8E4C42A60499100ED26A3 /* AccountDeletionViewController.swift */; };
F0E8E4C92A604E7400ED26A3 /* AccountDeletionInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E8E4C82A604E7400ED26A3 /* AccountDeletionInteractor.swift */; };
F0EF50D32A8FA47E0031E8DF /* ChangeLogInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0EF50D22A8FA47E0031E8DF /* ChangeLogInteractor.swift */; };
F0EF50D52A949F8E0031E8DF /* ChangeLogViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0EF50D42A949F8E0031E8DF /* ChangeLogViewModel.swift */; };
F0F316192BF3572B0078DBCF /* RelaySelectorResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0F316182BF3572B0078DBCF /* RelaySelectorResult.swift */; };
F0F3161B2BF358590078DBCF /* NoRelaysSatisfyingConstraintsError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0F3161A2BF358590078DBCF /* NoRelaysSatisfyingConstraintsError.swift */; };
Expand Down Expand Up @@ -2216,6 +2219,7 @@
F041BE4E2C983C2B0083EC28 /* DAITASettingsPromptItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAITASettingsPromptItem.swift; sourceTree = "<group>"; };
F041BE522C9878B60083EC28 /* ConnectionConfigurationBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionConfigurationBuilder.swift; sourceTree = "<group>"; };
F04413602BA45CD70018A6EE /* CustomListLocationNodeBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomListLocationNodeBuilder.swift; sourceTree = "<group>"; };
F048BFA12D31842B00251CB9 /* ChangeLogModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeLogModel.swift; sourceTree = "<group>"; };
F04AF92C2C466013004A8314 /* EphemeralPeerNegotiationState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EphemeralPeerNegotiationState.swift; sourceTree = "<group>"; };
F04DD3D72C130DF600E03E28 /* TunnelSettingsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelSettingsManager.swift; sourceTree = "<group>"; };
F04FBE602A8379EE009278D7 /* AppPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppPreferences.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2254,6 +2258,9 @@
F09A29792A9F8A9B00EA3B6F /* VoucherTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VoucherTextField.swift; sourceTree = "<group>"; };
F09A297A2A9F8A9B00EA3B6F /* RedeemVoucherContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedeemVoucherContentView.swift; sourceTree = "<group>"; };
F09A297F2A9F8AD200EA3B6F /* RedeemVoucherInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedeemVoucherInteractor.swift; sourceTree = "<group>"; };
F09C97202D311D7A00ADE747 /* ChangeLogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeLogView.swift; sourceTree = "<group>"; };
F09C97222D3122E400ADE747 /* ChangeLogReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeLogReader.swift; sourceTree = "<group>"; };
F09C97242D312ECD00ADE747 /* BulletPointText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BulletPointText.swift; sourceTree = "<group>"; };
F09D04AF2AE7F83D003D4F89 /* OutgoingConnectionProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutgoingConnectionProxy.swift; sourceTree = "<group>"; };
F09D04B42AE93CB6003D4F89 /* OutgoingConnectionProxy+Stub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OutgoingConnectionProxy+Stub.swift"; sourceTree = "<group>"; };
F09D04B62AE941DA003D4F89 /* OutgoingConnectionProxyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutgoingConnectionProxyTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2313,7 +2320,6 @@
F0E8E4C22A602E0D00ED26A3 /* AccountDeletionViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDeletionViewModel.swift; sourceTree = "<group>"; };
F0E8E4C42A60499100ED26A3 /* AccountDeletionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDeletionViewController.swift; sourceTree = "<group>"; };
F0E8E4C82A604E7400ED26A3 /* AccountDeletionInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDeletionInteractor.swift; sourceTree = "<group>"; };
F0EF50D22A8FA47E0031E8DF /* ChangeLogInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangeLogInteractor.swift; sourceTree = "<group>"; };
F0EF50D42A949F8E0031E8DF /* ChangeLogViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeLogViewModel.swift; sourceTree = "<group>"; };
F0F1EF8C2BE8FF0A00CED01D /* LaunchArguments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchArguments.swift; sourceTree = "<group>"; };
F0F316182BF3572B0078DBCF /* RelaySelectorResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelaySelectorResult.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4582,7 +4588,10 @@
F0EF50D12A8FA47E0031E8DF /* ChangeLog */ = {
isa = PBXGroup;
children = (
F0EF50D22A8FA47E0031E8DF /* ChangeLogInteractor.swift */,
F09C97242D312ECD00ADE747 /* BulletPointText.swift */,
F048BFA12D31842B00251CB9 /* ChangeLogModel.swift */,
F09C97222D3122E400ADE747 /* ChangeLogReader.swift */,
F09C97202D311D7A00ADE747 /* ChangeLogView.swift */,
F0EF50D42A949F8E0031E8DF /* ChangeLogViewModel.swift */,
);
path = ChangeLog;
Expand Down Expand Up @@ -5913,7 +5922,6 @@
7A3353932AAA089000F0A71C /* SimulatorTunnelInfo.swift in Sources */,
7A5869AB2B55527C00640D27 /* IPOverrideCoordinator.swift in Sources */,
5867771429097BCD006F721F /* PaymentState.swift in Sources */,
F0EF50D32A8FA47E0031E8DF /* ChangeLogInteractor.swift in Sources */,
7AC8A3AF2ABC71D600DC4939 /* TermsOfServiceCoordinator.swift in Sources */,
7A8A191A2CEF41AF000BCB5B /* GroupedRowView.swift in Sources */,
58FF9FE22B075BA600E4C97D /* EditAccessMethodSectionIdentifier.swift in Sources */,
Expand Down Expand Up @@ -5946,6 +5954,7 @@
586C0D892B03D5E000E7CDD7 /* TextCellContentConfiguration+Extensions.swift in Sources */,
58C3F4F92964B08300D72515 /* MapViewController.swift in Sources */,
584D26C6270C8741004EA533 /* SettingsDNSTextCell.swift in Sources */,
F09C97212D311D8800ADE747 /* ChangeLogView.swift in Sources */,
58F2E148276A307400A79513 /* MapConnectionStatusOperation.swift in Sources */,
58BA693123EADA6A009DC256 /* SimulatorTunnelProvider.swift in Sources */,
7A9CCCB32A96302800DD6A34 /* WelcomeCoordinator.swift in Sources */,
Expand Down Expand Up @@ -5989,6 +5998,7 @@
58B26E22294351EA00D5980C /* InAppNotificationProvider.swift in Sources */,
5893716A28817A45004EE76C /* DeviceManagementViewController.swift in Sources */,
7A9CCCB82A96302800DD6A34 /* SetupAccountCompletedCoordinator.swift in Sources */,
F09C97232D3122F300ADE747 /* ChangeLogReader.swift in Sources */,
447F3D8B2CDE1853006E3462 /* ShadowsocksObfuscationSettingsView.swift in Sources */,
58BFA5C622A7C97F00A6173D /* RelayCacheTracker.swift in Sources */,
7A0B311E2B303A0D004B12E0 /* AccessbilityIdentifier.swift in Sources */,
Expand Down Expand Up @@ -6152,6 +6162,7 @@
58677712290976FB006F721F /* SettingsInteractor.swift in Sources */,
58EF875D2B1638BF00C098B2 /* ProxyConfigurationTesterProtocol.swift in Sources */,
58CE5E66224146200008646E /* LoginViewController.swift in Sources */,
F048BFA22D31843000251CB9 /* ChangeLogModel.swift in Sources */,
F0C6FA852A6A733700F521F0 /* InAppPurchaseInteractor.swift in Sources */,
58CEB2F92AFD136E00E6E088 /* UIBackgroundConfiguration+Extensions.swift in Sources */,
5878F50029CDA742003D4BE2 /* UIView+AutoLayoutBuilder.swift in Sources */,
Expand Down Expand Up @@ -6298,6 +6309,7 @@
5803B4B22940A48700C23744 /* TunnelStore.swift in Sources */,
586A950F29012BEE007BAF2B /* AddressCacheTracker.swift in Sources */,
7A7907332BC0280A00B61F81 /* InterceptibleNavigationController.swift in Sources */,
F09C97252D312ED000ADE747 /* BulletPointText.swift in Sources */,
F02F41A02B9723AF00625A4F /* AddLocationsViewController.swift in Sources */,
587B753D2666468F00DEF7E9 /* NotificationController.swift in Sources */,
);
Expand Down
18 changes: 8 additions & 10 deletions ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -332,16 +332,15 @@ final class ApplicationCoordinator: Coordinator, Presenting, @preconcurrency Roo
}

private func presentChangeLog(animated: Bool, completion: @escaping (Coordinator) -> Void) {
let coordinator = ChangeLogCoordinator(interactor: ChangeLogInteractor())

coordinator.didFinish = { [weak self] _ in
self?.appPreferences.markChangeLogSeen()
self?.router.dismiss(.changelog)
}
let coordinator = ChangeLogCoordinator(
navigationController: CustomNavigationController(),
viewModel: ChangeLogViewModel(changeLogReader: ChangeLogReader())
)

coordinator.start()
coordinator.start(animated: false)

presentChild(coordinator, animated: animated) {
presentChild(coordinator, animated: animated) { [weak self] in
self?.appPreferences.markChangeLogSeen()
completion(coordinator)
}
}
Expand Down Expand Up @@ -824,8 +823,7 @@ extension DeviceState {

fileprivate extension AppPreferencesDataSource {
var hasSeenLastChanges: Bool {
!ChangeLogInteractor().hasNewChanges ||
(lastSeenChangeLogVersion == Bundle.main.shortVersion)
lastSeenChangeLogVersion == Bundle.main.shortVersion
}

mutating func markChangeLogSeen() {
Expand Down
51 changes: 19 additions & 32 deletions ios/MullvadVPN/Coordinators/ChangeLogCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,33 @@

import MullvadLogging
import Routing
import SwiftUI
import UIKit

final class ChangeLogCoordinator: Coordinator, Presentable {
private var alertController: AlertViewController?
private let interactor: ChangeLogInteractor
var didFinish: ((ChangeLogCoordinator) -> Void)?
final class ChangeLogCoordinator: Coordinator, Presentable, SettingsChildCoordinator {
private var navigationController: UINavigationController?
private let viewModel: ChangeLogViewModel

var presentedViewController: UIViewController {
return alertController!
return navigationController!
}

init(interactor: ChangeLogInteractor) {
self.interactor = interactor
init(navigationController: UINavigationController, viewModel: ChangeLogViewModel) {
self.viewModel = viewModel
self.navigationController = navigationController
}

func start() {
let presentation = AlertPresentation(
id: "change-log-ok-alert",
accessibilityIdentifier: .changeLogAlert,
header: interactor.viewModel.header,
title: interactor.viewModel.title,
attributedMessage: interactor.viewModel.body,
buttons: [
AlertAction(
title: NSLocalizedString(
"CHANGE_LOG_OK_ACTION",
tableName: "Account",
value: "Got it!",
comment: ""
),
style: .default,
accessibilityId: .alertOkButton,
handler: { [weak self] in
guard let self else { return }
didFinish?(self)
}
),
]
func start(animated: Bool) {
let changeLogViewController = UIHostingController(rootView: ChangeLogView(viewModel: viewModel))
changeLogViewController.view.setAccessibilityIdentifier(.changeLogAlert)
changeLogViewController.navigationItem.title = NSLocalizedString(
"whats_new_title",
tableName: "Changelog",
value: "What's new",
comment: ""
)

alertController = AlertViewController(presentation: presentation)
changeLogViewController.navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.pushViewController(changeLogViewController, animated: animated)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ enum SettingsNavigationRoute: Equatable {
/// API access route.
case apiAccess

/// changelog route.
case changelog

/// Multihop route.
case multihop

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,17 @@ struct SettingsViewControllerFactory {
case .root:
// Handled in SettingsCoordinator.
.failed
case .faq:
// Handled separately and presented as a modal.
.failed
case .vpnSettings:
makeVPNSettingsViewController()
case .problemReport:
makeProblemReportViewController()
case .apiAccess:
makeAPIAccessViewController()
case .faq:
// Handled separately and presented as a modal.
.failed
case .changelog:
makeChangelogViewController()
case .multihop:
makeMultihopViewController()
case .daita:
Expand Down Expand Up @@ -93,6 +95,15 @@ struct SettingsViewControllerFactory {
))
}

private func makeChangelogViewController() -> MakeChildResult {
return .childCoordinator(
ChangeLogCoordinator(
navigationController: navigationController,
viewModel: ChangeLogViewModel(changeLogReader: ChangeLogReader())
)
)
}

private func makeMultihopViewController() -> MakeChildResult {
let viewModel = MultihopTunnelSettingsViewModel(tunnelManager: interactorFactory.tunnelManager)
let view = SettingsMultihopView(tunnelViewModel: viewModel)
Expand Down
27 changes: 27 additions & 0 deletions ios/MullvadVPN/View controllers/ChangeLog/BulletPointText.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// BulletPointText.swift
// MullvadVPN
//
// Created by Mojgan on 2025-01-10.
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
import SwiftUI

struct BulletPointText: View {
let text: String
let bullet = ""

var body: some View {
HStack(alignment: .firstTextBaseline) {
Text(bullet)
.font(.body)
.foregroundColor(UIColor.secondaryTextColor.color)
Text(text)
.font(.body)
.foregroundColor(UIColor.secondaryTextColor.color)
.lineLimit(nil)
.multilineTextAlignment(.leading)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}

This file was deleted.

12 changes: 12 additions & 0 deletions ios/MullvadVPN/View controllers/ChangeLog/ChangeLogModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// ChangeLogModel.swift
// MullvadVPN
//
// Created by Mojgan on 2025-01-10.
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//

struct ChangeLogModel {
let title: String
let changes: [String]
}
Loading

0 comments on commit cbca8a7

Please sign in to comment.