Skip to content

Commit

Permalink
Use protocol instead of keyPath for storing settings
Browse files Browse the repository at this point in the history
  • Loading branch information
dus7 committed Sep 12, 2024
1 parent b3699de commit 6b7f0f5
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 50 deletions.
20 changes: 8 additions & 12 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,8 @@
6FD8E5202C5BA23200345670 /* NewTabPageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FD8E51F2C5BA23200345670 /* NewTabPageModel.swift */; };
6FD8E5222C5BA5C400345670 /* NewTabPageIntroMessageSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FD8E5212C5BA5C400345670 /* NewTabPageIntroMessageSetup.swift */; };
6FDA1FB32B59584400AC962A /* AddressDisplayHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDA1FB22B59584400AC962A /* AddressDisplayHelper.swift */; };
6FDC63FF2C906DD300DB71B3 /* NewTabPageStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDC63FE2C906DD300DB71B3 /* NewTabPageStorage.swift */; };
6FDC64012C92F4A300DB71B3 /* NewTabPageIntroDataStoring.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDC64002C92F4A300DB71B3 /* NewTabPageIntroDataStoring.swift */; };
6FDC64032C92F4D600DB71B3 /* NewTabPageSettingsPersistentStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDC64022C92F4D600DB71B3 /* NewTabPageSettingsPersistentStore.swift */; };
6FE018402C25CB3F001F680D /* FavoritesSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FE0183F2C25CB3F001F680D /* FavoritesSectionHeader.swift */; };
6FE095D82BD90AFB00490FF8 /* UniversalOmniBarState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FE095D72BD90AFB00490FF8 /* UniversalOmniBarState.swift */; };
6FE127382C20492500EB5724 /* NewTabPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FE127372C20492500EB5724 /* NewTabPage.swift */; };
Expand Down Expand Up @@ -1591,7 +1592,8 @@
6FD8E51F2C5BA23200345670 /* NewTabPageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTabPageModel.swift; sourceTree = "<group>"; };
6FD8E5212C5BA5C400345670 /* NewTabPageIntroMessageSetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTabPageIntroMessageSetup.swift; sourceTree = "<group>"; };
6FDA1FB22B59584400AC962A /* AddressDisplayHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressDisplayHelper.swift; sourceTree = "<group>"; };
6FDC63FE2C906DD300DB71B3 /* NewTabPageStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTabPageStorage.swift; sourceTree = "<group>"; };
6FDC64002C92F4A300DB71B3 /* NewTabPageIntroDataStoring.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTabPageIntroDataStoring.swift; sourceTree = "<group>"; };
6FDC64022C92F4D600DB71B3 /* NewTabPageSettingsPersistentStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTabPageSettingsPersistentStore.swift; sourceTree = "<group>"; };
6FE0183F2C25CB3F001F680D /* FavoritesSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesSectionHeader.swift; sourceTree = "<group>"; };
6FE095D72BD90AFB00490FF8 /* UniversalOmniBarState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UniversalOmniBarState.swift; sourceTree = "<group>"; };
6FE127372C20492500EB5724 /* NewTabPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTabPage.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3803,6 +3805,7 @@
6F5345AE2C53F2DE00424A43 /* NewTabPageSettingsPersistentStorage.swift */,
6F9FFE252C579BCD00A238BE /* NewTabPageShortcutsSettingsStorage.swift */,
6F9FFE272C579DEA00A238BE /* NewTabPageSectionsSettingsStorage.swift */,
6FDC64022C92F4D600DB71B3 /* NewTabPageSettingsPersistentStore.swift */,
);
name = Storage;
sourceTree = "<group>";
Expand Down Expand Up @@ -3871,22 +3874,14 @@
children = (
6FD8E51D2C5B84DE00345670 /* NewTabPageIntroMessageView.swift */,
6FD8E5212C5BA5C400345670 /* NewTabPageIntroMessageSetup.swift */,
6FDC64002C92F4A300DB71B3 /* NewTabPageIntroDataStoring.swift */,
);
name = IntroMessage;
sourceTree = "<group>";
};
6FDC63FD2C906DBB00DB71B3 /* Storage */ = {
isa = PBXGroup;
children = (
6FDC63FE2C906DD300DB71B3 /* NewTabPageStorage.swift */,
);
name = Storage;
sourceTree = "<group>";
};
6FE127362C20436A00EB5724 /* HomeRedesign */ = {
isa = PBXGroup;
children = (
6FDC63FD2C906DBB00DB71B3 /* Storage */,
6FE1273B2C204C0D00EB5724 /* Subviews */,
6F03CAF82C32C3AA004179A8 /* Messages */,
6FE127372C20492500EB5724 /* NewTabPage.swift */,
Expand Down Expand Up @@ -7241,6 +7236,7 @@
F4E1936625AF722F001D2666 /* HighlightCutOutView.swift in Sources */,
6FB2A67C2C2D9DF0004D20C8 /* FavoritesEmptyStateView.swift in Sources */,
1E162605296840D80004127F /* Triangle.swift in Sources */,
6FDC64012C92F4A300DB71B3 /* NewTabPageIntroDataStoring.swift in Sources */,
B609D5522862EAFF0088CAC2 /* InlineWKDownloadDelegate.swift in Sources */,
BDFF03222BA3D8E200F324C9 /* NetworkProtectionFeatureVisibility.swift in Sources */,
B652DEFD287BE67400C12A9C /* UserScripts.swift in Sources */,
Expand Down Expand Up @@ -7322,6 +7318,7 @@
6FB2A67A2C2C5BAE004D20C8 /* FavoriteEmptyStateItem.swift in Sources */,
6FBF0F8B2BD7C0A900136CF0 /* AllProtectedCell.swift in Sources */,
9F4CC5242C4A4F0D006A96EB /* SwiftUITestUtilities.swift in Sources */,
6FDC64032C92F4D600DB71B3 /* NewTabPageSettingsPersistentStore.swift in Sources */,
1E4F4A5A297193DE00625985 /* MainViewController+CookiesManaged.swift in Sources */,
C12324C32C4697C900FBB26B /* AutofillBreakageReportTableViewCell.swift in Sources */,
8586A10D24CBA7070049720E /* FindInPageActivity.swift in Sources */,
Expand Down Expand Up @@ -7422,7 +7419,6 @@
85F2FFCF2211F8E5006BB258 /* TabSwitcherViewController+KeyCommands.swift in Sources */,
3157B43327F497E90042D3D7 /* SaveLoginView.swift in Sources */,
F17922E01E71BB59006E3D97 /* AutocompleteViewControllerDelegate.swift in Sources */,
6FDC63FF2C906DD300DB71B3 /* NewTabPageStorage.swift in Sources */,
BDE91CDC2C62AA3A0005CB74 /* DefaultMetadataCollector.swift in Sources */,
D664C7C82B289AA200CBFA76 /* SubscriptionFlowView.swift in Sources */,
EE458D142ABB652900FC651A /* NetworkProtectionDebugUtilities.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// NewTabPageStorage.swift
// NewTabPageIntroDataStoring.swift
// DuckDuckGo
//
// Copyright © 2024 DuckDuckGo. All rights reserved.
Expand All @@ -25,23 +25,10 @@ protocol NewTabPageIntroDataStoring: AnyObject {
var newTabPageIntroMessageSeenCount: Int { get set }
}

protocol NewTabPageSettingsDataStoring: AnyObject {
var newTabPageShortcutsSettings: Data? { get set }
var newTabPageSectionsSettings: Data? { get set }
}

final class NewTabPageIntroDataUserDefaultsStorage: NewTabPageIntroDataStoring {
@UserDefaultsWrapper(key: .newTabPageIntroMessageEnabled, defaultValue: nil)
var newTabPageIntroMessageEnabled: Bool?

@UserDefaultsWrapper(key: .newTabPageIntroMessageSeenCount, defaultValue: 0)
var newTabPageIntroMessageSeenCount: Int
}

final class NewTabPageSettingsDataUserDefaultsStorage: NewTabPageSettingsDataStoring {
@UserDefaultsWrapper(key: .newTabPageShortcutsSettings, defaultValue: nil)
var newTabPageShortcutsSettings: Data?

@UserDefaultsWrapper(key: .newTabPageSectionsSettings, defaultValue: nil)
var newTabPageSectionsSettings: Data?
}
5 changes: 3 additions & 2 deletions DuckDuckGo/NewTabPageSectionsSettingsStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ enum NewTabPageSection: String, Codable, CaseIterable {

typealias NewTabPageSectionsSettingsStorage = NewTabPageSettingsPersistentStorage<NewTabPageSection>



extension NewTabPageSettingsPersistentStorage<NewTabPageSection> {
convenience init() {
self.init(persistence: NewTabPageSettingsDataUserDefaultsStorage(),
keyPath: \.newTabPageSectionsSettings,
self.init(persistentStore: NewTabPageSectionsSettingsStore(),
defaultOrder: NewTabPageSection.allCases,
defaultEnabledItems: NewTabPageSection.allCases)
}
Expand Down
17 changes: 9 additions & 8 deletions DuckDuckGo/NewTabPageSettingsPersistentStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,20 @@ private struct NewTabPageItemSettings<Item: NewTabPageSettingsStorageItem>: Coda
let enabledItems: Set<Item>
}

protocol NewTabPageSettingsPersistentStore: AnyObject {
var data: Data? { get set }
}

final class NewTabPageSettingsPersistentStorage<Item: NewTabPageSettingsStorageItem>: NewTabPageSettingsStorage {
private(set) var itemsOrder: [Item]
private var enabledItems: Set<Item>

private var persistence: NewTabPageSettingsDataStoring
private let keyPath: WritableKeyPath<NewTabPageSettingsDataStoring, Data?>
private var persistentStore: any NewTabPageSettingsPersistentStore

init(persistence: NewTabPageSettingsDataStoring,
keyPath: WritableKeyPath<NewTabPageSettingsDataStoring, Data?>,
init(persistentStore: NewTabPageSettingsPersistentStore,
defaultOrder: [Item],
defaultEnabledItems: [Item]) {
self.persistence = persistence
self.keyPath = keyPath
self.persistentStore = persistentStore
self.itemsOrder = defaultOrder
self.enabledItems = Set(defaultEnabledItems)

Expand All @@ -62,12 +63,12 @@ final class NewTabPageSettingsPersistentStorage<Item: NewTabPageSettingsStorageI
func save() {
let newSettings = NewTabPageItemSettings(itemsOrder: itemsOrder, enabledItems: enabledItems)
if let data = try? JSONEncoder().encode(newSettings) {
persistence[keyPath: keyPath] = data
persistentStore.data = data
}
}

private func load() {
if let settingsData = persistence[keyPath: keyPath],
if let settingsData = persistentStore.data,
let settings = try? JSONDecoder().decode(NewTabPageItemSettings<Item>.self, from: settingsData) {
itemsOrder = settings.itemsOrder
enabledItems = settings.enabledItems
Expand Down
31 changes: 31 additions & 0 deletions DuckDuckGo/NewTabPageSettingsPersistentStore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// NewTabPageSettingsPersistentStore.swift
// DuckDuckGo
//
// Copyright © 2024 DuckDuckGo. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation
import Core

final class NewTabPageShorctutsSettingsStore: NewTabPageSettingsPersistentStore {
@UserDefaultsWrapper(key: .newTabPageShortcutsSettings, defaultValue: nil)
var data: Data?
}

final class NewTabPageSectionsSettingsStore: NewTabPageSettingsPersistentStore {
@UserDefaultsWrapper(key: .newTabPageSectionsSettings, defaultValue: nil)
var data: Data?
}
3 changes: 1 addition & 2 deletions DuckDuckGo/NewTabPageShortcutsSettingsStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ typealias NewTabPageShortcutsSettingsStorage = NewTabPageSettingsPersistentStora

extension NewTabPageSettingsPersistentStorage<NewTabPageShortcut> {
convenience init() {
self.init(persistence: NewTabPageSettingsDataUserDefaultsStorage(),
keyPath: \.newTabPageShortcutsSettings,
self.init(persistentStore: NewTabPageShorctutsSettingsStore(),
defaultOrder: NewTabPageShortcut.allCases,
defaultEnabledItems: NewTabPageShortcut.allCases)
}
Expand Down
8 changes: 3 additions & 5 deletions DuckDuckGoTests/NewTabPageSectionsSettingsModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ final class NewTabPageSectionsSettingsModelTests: XCTestCase {

private func createSUT() -> NewTabPageSectionsSettingsModel {
let storage = NewTabPageSectionsSettingsStorage(
persistence: NewTabPageSettingsDataStoringMock(),
keyPath: \.newTabPageSectionsSettings,
persistentStore: NewTabPageSettingsPersistentStoreMock(),
defaultOrder: NewTabPageSection.allCases,
defaultEnabledItems: NewTabPageSection.allCases
)
Expand All @@ -70,7 +69,6 @@ final class NewTabPageSectionsSettingsModelTests: XCTestCase {
}
}

final class NewTabPageSettingsDataStoringMock: NewTabPageSettingsDataStoring {
var newTabPageSectionsSettings: Data?
var newTabPageShortcutsSettings: Data?
final class NewTabPageSettingsPersistentStoreMock: NewTabPageSettingsPersistentStore {
var data: Data?
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import XCTest

final class NewTabPageSettingsPersistentStorageTests: XCTestCase {

private var settingsDataStorage = NewTabPageSettingsDataStoringMock()
private var settingsPersistentStore = NewTabPageSettingsPersistentStoreMock()

func testLoadsInitialStateFromDefaults() {
let sut = createSUT()
Expand All @@ -35,7 +35,7 @@ final class NewTabPageSettingsPersistentStorageTests: XCTestCase {
func testUsesDefaultsIfDataCorrupted() {
let sut = createSUT()

settingsDataStorage[keyPath: Constant.keyPath] = "Random data".data(using: .utf8)
settingsPersistentStore.data = "Random data".data(using: .utf8)

XCTAssertEqual(sut.itemsOrder, Constant.defaultItems)
XCTAssertEqual(sut.enabledItems, Constant.defaultItems)
Expand Down Expand Up @@ -90,15 +90,13 @@ final class NewTabPageSettingsPersistentStorageTests: XCTestCase {
}

private func createSUT(defaultOrder: [StorageItem] = Constant.defaultItems, defaultEnabledItems: [StorageItem] = Constant.defaultItems) -> NewTabPageSettingsPersistentStorage<StorageItem> {
NewTabPageSettingsPersistentStorage<StorageItem>(persistence: settingsDataStorage,
keyPath: Constant.keyPath,
NewTabPageSettingsPersistentStorage<StorageItem>(persistentStore: settingsPersistentStore,
defaultOrder: defaultOrder,
defaultEnabledItems: defaultEnabledItems)
}

private enum Constant {
static let defaultItems = [StorageItem.one, .two, .three]
static let keyPath = \NewTabPageSettingsDataStoring.newTabPageSectionsSettings
}
}

Expand Down
3 changes: 1 addition & 2 deletions DuckDuckGoTests/NewTabPageShortcutsSettingsModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ final class NewTabPageShortcutsSettingsModelTests: XCTestCase {

private func createSUT() -> NewTabPageShortcutsSettingsModel {
let storage = NewTabPageShortcutsSettingsStorage(
persistence: NewTabPageSettingsDataStoringMock(),
keyPath: \.newTabPageShortcutsSettings,
persistentStore: NewTabPageSettingsPersistentStoreMock(),
defaultOrder: NewTabPageShortcut.allCases,
defaultEnabledItems: NewTabPageShortcut.allCases
)
Expand Down

0 comments on commit 6b7f0f5

Please sign in to comment.