[Features] Adds @Feature property wrapper
Simplifies defining feature flags that can enabled + disabled via UserDefaults.
This commit is contained in:
parent
3fb7e8b4b7
commit
d613cc9ad7
@ -186,6 +186,7 @@
|
||||
D5D797E9298DCC7300738869 /* cheatbase.zip in Resources */ = {isa = PBXBuildFile; fileRef = D5D797E7298DC9E200738869 /* cheatbase.zip */; };
|
||||
D5D7C1FA29E60EDE00663793 /* libDeltaFeatures.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5D7C1F129E60DFF00663793 /* libDeltaFeatures.a */; };
|
||||
D5D7C20429E60F2000663793 /* Feature.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A9BFFD29DDECF100A8D610 /* Feature.swift */; };
|
||||
D5D7C20829E616CF00663793 /* FeatureContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D7C20729E616CF00663793 /* FeatureContainer.swift */; };
|
||||
D5F82FB82981D3AC00B229AF /* LegacySearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F82FB72981D3AC00B229AF /* LegacySearchBar.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -419,6 +420,7 @@
|
||||
D5D797E5298D946200738869 /* Contributor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Contributor.swift; sourceTree = "<group>"; };
|
||||
D5D797E7298DC9E200738869 /* cheatbase.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = cheatbase.zip; sourceTree = "<group>"; };
|
||||
D5D7C1F129E60DFF00663793 /* libDeltaFeatures.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDeltaFeatures.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D5D7C20729E616CF00663793 /* FeatureContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureContainer.swift; sourceTree = "<group>"; };
|
||||
D5F82FB72981D3AC00B229AF /* LegacySearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacySearchBar.swift; sourceTree = "<group>"; };
|
||||
DC866E433B3BA9AE18ABA1EC /* libPods-Delta.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Delta.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
@ -1013,6 +1015,7 @@
|
||||
children = (
|
||||
D5A9BFFD29DDECF100A8D610 /* Feature.swift */,
|
||||
D517F6BB29E737F5000D14D0 /* Types */,
|
||||
D5D7C1FE29E60EF700663793 /* Protocols */,
|
||||
D5D7C1F829E60E8600663793 /* Extensions */,
|
||||
);
|
||||
path = DeltaFeatures;
|
||||
@ -1026,6 +1029,14 @@
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D5D7C1FE29E60EF700663793 /* Protocols */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D5D7C20729E616CF00663793 /* FeatureContainer.swift */,
|
||||
);
|
||||
path = Protocols;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FD1E8AE87FA2DB8793F7B937 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1504,6 +1515,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D5D7C20829E616CF00663793 /* FeatureContainer.swift in Sources */,
|
||||
D517F6BA29E730DA000D14D0 /* SettingsName.swift in Sources */,
|
||||
D5D7C20429E60F2000663793 /* Feature.swift in Sources */,
|
||||
D54F710429E89DFC009C069A /* NotificationName+Settings.swift in Sources */,
|
||||
|
||||
@ -6,5 +6,43 @@
|
||||
// Copyright © 2023 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import Combine
|
||||
|
||||
@propertyWrapper @dynamicMemberLookup
|
||||
public final class Feature
|
||||
{
|
||||
public let name: LocalizedStringKey
|
||||
public let description: LocalizedStringKey?
|
||||
|
||||
// Assigned to property name.
|
||||
public internal(set) var key: String = ""
|
||||
|
||||
// Used for `SettingsUserInfoKey.name` value in .settingsDidChange notification.
|
||||
public var settingsKey: SettingsName {
|
||||
return SettingsName(rawValue: self.key)
|
||||
}
|
||||
|
||||
public var isEnabled: Bool {
|
||||
get {
|
||||
let isEnabled = UserDefaults.standard.bool(forKey: self.key)
|
||||
return isEnabled
|
||||
}
|
||||
set {
|
||||
self.objectWillChange.send()
|
||||
UserDefaults.standard.set(newValue, forKey: self.key)
|
||||
|
||||
NotificationCenter.default.post(name: .settingsDidChange, object: nil, userInfo: [SettingsUserInfoKey.name: self.settingsKey, SettingsUserInfoKey.value: newValue])
|
||||
}
|
||||
}
|
||||
|
||||
public var wrappedValue: Feature {
|
||||
return self
|
||||
}
|
||||
|
||||
public init(name: LocalizedStringKey, description: LocalizedStringKey? = nil)
|
||||
{
|
||||
self.name = name
|
||||
self.description = description
|
||||
}
|
||||
}
|
||||
|
||||
36
DeltaFeatures/Protocols/FeatureContainer.swift
Normal file
36
DeltaFeatures/Protocols/FeatureContainer.swift
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// FeatureContainer.swift
|
||||
// DeltaFeatures
|
||||
//
|
||||
// Created by Riley Testut on 4/11/23.
|
||||
// Copyright © 2023 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol FeatureContainer
|
||||
{
|
||||
static var shared: Self { get }
|
||||
}
|
||||
|
||||
public extension FeatureContainer
|
||||
{
|
||||
var allFeatures: [Feature] {
|
||||
let features = Mirror(reflecting: self).children.compactMap { (child) -> Feature? in
|
||||
let feature = child.value as? Feature
|
||||
return feature
|
||||
}
|
||||
return features
|
||||
}
|
||||
|
||||
func prepareFeatures()
|
||||
{
|
||||
// Assign keys to property names.
|
||||
for case (let key?, let feature as Feature) in Mirror(reflecting: self).children
|
||||
{
|
||||
// Remove leading underscore.
|
||||
let sanitizedKey = key.dropFirst()
|
||||
feature.key = String(sanitizedKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user