Skip to content

Commit 40db0ba

Browse files
prachigauriarPrachi Gauriar
andauthored
Add Editor UI (#11)
- Add a SwiftUI configuration variable editor with list and detail views for browsing and overriding configuration values at runtime - Add EditorOverrideProvider, a persistent configuration provider backed by UserDefaults that integrates with ConfigVariableReader - Add EditorDocument to manage a working copy of overrides with undo/redo and dirty tracking - Add MVVM layer with ConfigVariableListView, ConfigVariableDetailView, and their view model protocols and implementations - Add ConfigVariableEditor as the public entry point for presenting the editor - Add ProviderBadge and ProviderValue utility views for displaying provider information - Add EditorControl to describe which UI control the editor uses for each variable type - Add DisplayNameMetadataKey and RequiresRelaunchMetadataKey for editor metadata - Add ConfigContent editing support with displayString, editorControl, parse, and defaultContent on content types - Add NamedConfigProvider and ProviderEditorSnapshot data models - Add ConfigSnapshot+ConfigContent extension - Refactor ConfigVariableSecrecy enum into an isSecret boolean on ConfigVariable - Add destinationTypeName to RegisteredConfigVariable - Add localized string catalog for all editor UI strings - Add example app for exercising the editor --------- Co-authored-by: Prachi Gauriar <prachi@gauriar.com>
1 parent 3cb0757 commit 40db0ba

63 files changed

Lines changed: 6436 additions & 338 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

App/App.xcodeproj/project.pbxproj

Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
// !$*UTF8*$!
2+
{
3+
archiveVersion = 1;
4+
classes = {
5+
};
6+
objectVersion = 77;
7+
objects = {
8+
9+
/* Begin PBXBuildFile section */
10+
4C23D0F52F5E005000666984 /* DevConfiguration in Frameworks */ = {isa = PBXBuildFile; productRef = 4C23D0F42F5E005000666984 /* DevConfiguration */; };
11+
/* End PBXBuildFile section */
12+
13+
/* Begin PBXFileReference section */
14+
4C23D0E12F5DFFE700666984 /* ExampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ExampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
15+
/* End PBXFileReference section */
16+
17+
/* Begin PBXFileSystemSynchronizedRootGroup section */
18+
4C23D0E32F5DFFE700666984 /* Sources */ = {
19+
isa = PBXFileSystemSynchronizedRootGroup;
20+
path = Sources;
21+
sourceTree = "<group>";
22+
};
23+
/* End PBXFileSystemSynchronizedRootGroup section */
24+
25+
/* Begin PBXFrameworksBuildPhase section */
26+
4C23D0DE2F5DFFE700666984 /* Frameworks */ = {
27+
isa = PBXFrameworksBuildPhase;
28+
buildActionMask = 2147483647;
29+
files = (
30+
4C23D0F52F5E005000666984 /* DevConfiguration in Frameworks */,
31+
);
32+
runOnlyForDeploymentPostprocessing = 0;
33+
};
34+
/* End PBXFrameworksBuildPhase section */
35+
36+
/* Begin PBXGroup section */
37+
4C23D0D82F5DFFE700666984 = {
38+
isa = PBXGroup;
39+
children = (
40+
4C23D0E32F5DFFE700666984 /* Sources */,
41+
4C23D0E22F5DFFE700666984 /* Products */,
42+
);
43+
sourceTree = "<group>";
44+
};
45+
4C23D0E22F5DFFE700666984 /* Products */ = {
46+
isa = PBXGroup;
47+
children = (
48+
4C23D0E12F5DFFE700666984 /* ExampleApp.app */,
49+
);
50+
name = Products;
51+
sourceTree = "<group>";
52+
};
53+
/* End PBXGroup section */
54+
55+
/* Begin PBXNativeTarget section */
56+
4C23D0E02F5DFFE700666984 /* ExampleApp */ = {
57+
isa = PBXNativeTarget;
58+
buildConfigurationList = 4C23D0EC2F5DFFE800666984 /* Build configuration list for PBXNativeTarget "ExampleApp" */;
59+
buildPhases = (
60+
4C23D0DD2F5DFFE700666984 /* Sources */,
61+
4C23D0DE2F5DFFE700666984 /* Frameworks */,
62+
4C23D0DF2F5DFFE700666984 /* Resources */,
63+
);
64+
buildRules = (
65+
);
66+
dependencies = (
67+
);
68+
fileSystemSynchronizedGroups = (
69+
4C23D0E32F5DFFE700666984 /* Sources */,
70+
);
71+
name = ExampleApp;
72+
packageProductDependencies = (
73+
4C23D0F42F5E005000666984 /* DevConfiguration */,
74+
);
75+
productName = ExampleApp;
76+
productReference = 4C23D0E12F5DFFE700666984 /* ExampleApp.app */;
77+
productType = "com.apple.product-type.application";
78+
};
79+
/* End PBXNativeTarget section */
80+
81+
/* Begin PBXProject section */
82+
4C23D0D92F5DFFE700666984 /* Project object */ = {
83+
isa = PBXProject;
84+
attributes = {
85+
BuildIndependentTargetsInParallel = 1;
86+
LastSwiftUpdateCheck = 2630;
87+
LastUpgradeCheck = 2630;
88+
TargetAttributes = {
89+
4C23D0E02F5DFFE700666984 = {
90+
CreatedOnToolsVersion = 26.3;
91+
};
92+
};
93+
};
94+
buildConfigurationList = 4C23D0DC2F5DFFE700666984 /* Build configuration list for PBXProject "App" */;
95+
developmentRegion = en;
96+
hasScannedForEncodings = 0;
97+
knownRegions = (
98+
en,
99+
Base,
100+
);
101+
mainGroup = 4C23D0D82F5DFFE700666984;
102+
minimizedProjectReferenceProxies = 1;
103+
packageReferences = (
104+
4C23D0F32F5E005000666984 /* XCLocalSwiftPackageReference "../../DevConfiguration" */,
105+
);
106+
preferredProjectObjectVersion = 77;
107+
productRefGroup = 4C23D0E22F5DFFE700666984 /* Products */;
108+
projectDirPath = "";
109+
projectRoot = "";
110+
targets = (
111+
4C23D0E02F5DFFE700666984 /* ExampleApp */,
112+
);
113+
};
114+
/* End PBXProject section */
115+
116+
/* Begin PBXResourcesBuildPhase section */
117+
4C23D0DF2F5DFFE700666984 /* Resources */ = {
118+
isa = PBXResourcesBuildPhase;
119+
buildActionMask = 2147483647;
120+
files = (
121+
);
122+
runOnlyForDeploymentPostprocessing = 0;
123+
};
124+
/* End PBXResourcesBuildPhase section */
125+
126+
/* Begin PBXSourcesBuildPhase section */
127+
4C23D0DD2F5DFFE700666984 /* Sources */ = {
128+
isa = PBXSourcesBuildPhase;
129+
buildActionMask = 2147483647;
130+
files = (
131+
);
132+
runOnlyForDeploymentPostprocessing = 0;
133+
};
134+
/* End PBXSourcesBuildPhase section */
135+
136+
/* Begin XCBuildConfiguration section */
137+
4C23D0EA2F5DFFE800666984 /* Debug */ = {
138+
isa = XCBuildConfiguration;
139+
buildSettings = {
140+
ALWAYS_SEARCH_USER_PATHS = NO;
141+
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
142+
CLANG_ANALYZER_NONNULL = YES;
143+
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
144+
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
145+
CLANG_ENABLE_MODULES = YES;
146+
CLANG_ENABLE_OBJC_ARC = YES;
147+
CLANG_ENABLE_OBJC_WEAK = YES;
148+
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
149+
CLANG_WARN_BOOL_CONVERSION = YES;
150+
CLANG_WARN_COMMA = YES;
151+
CLANG_WARN_CONSTANT_CONVERSION = YES;
152+
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
153+
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
154+
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
155+
CLANG_WARN_EMPTY_BODY = YES;
156+
CLANG_WARN_ENUM_CONVERSION = YES;
157+
CLANG_WARN_INFINITE_RECURSION = YES;
158+
CLANG_WARN_INT_CONVERSION = YES;
159+
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
160+
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
161+
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
162+
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
163+
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
164+
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
165+
CLANG_WARN_STRICT_PROTOTYPES = YES;
166+
CLANG_WARN_SUSPICIOUS_MOVE = YES;
167+
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
168+
CLANG_WARN_UNREACHABLE_CODE = YES;
169+
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
170+
COPY_PHASE_STRIP = NO;
171+
DEBUG_INFORMATION_FORMAT = dwarf;
172+
ENABLE_STRICT_OBJC_MSGSEND = YES;
173+
ENABLE_TESTABILITY = YES;
174+
ENABLE_USER_SCRIPT_SANDBOXING = YES;
175+
GCC_C_LANGUAGE_STANDARD = gnu17;
176+
GCC_DYNAMIC_NO_PIC = NO;
177+
GCC_NO_COMMON_BLOCKS = YES;
178+
GCC_OPTIMIZATION_LEVEL = 0;
179+
GCC_PREPROCESSOR_DEFINITIONS = (
180+
"DEBUG=1",
181+
"$(inherited)",
182+
);
183+
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
184+
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
185+
GCC_WARN_UNDECLARED_SELECTOR = YES;
186+
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
187+
GCC_WARN_UNUSED_FUNCTION = YES;
188+
GCC_WARN_UNUSED_VARIABLE = YES;
189+
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
190+
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
191+
MTL_FAST_MATH = YES;
192+
ONLY_ACTIVE_ARCH = YES;
193+
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
194+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
195+
};
196+
name = Debug;
197+
};
198+
4C23D0EB2F5DFFE800666984 /* Release */ = {
199+
isa = XCBuildConfiguration;
200+
buildSettings = {
201+
ALWAYS_SEARCH_USER_PATHS = NO;
202+
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
203+
CLANG_ANALYZER_NONNULL = YES;
204+
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
205+
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
206+
CLANG_ENABLE_MODULES = YES;
207+
CLANG_ENABLE_OBJC_ARC = YES;
208+
CLANG_ENABLE_OBJC_WEAK = YES;
209+
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
210+
CLANG_WARN_BOOL_CONVERSION = YES;
211+
CLANG_WARN_COMMA = YES;
212+
CLANG_WARN_CONSTANT_CONVERSION = YES;
213+
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
214+
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
215+
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
216+
CLANG_WARN_EMPTY_BODY = YES;
217+
CLANG_WARN_ENUM_CONVERSION = YES;
218+
CLANG_WARN_INFINITE_RECURSION = YES;
219+
CLANG_WARN_INT_CONVERSION = YES;
220+
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
221+
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
222+
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
223+
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
224+
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
225+
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
226+
CLANG_WARN_STRICT_PROTOTYPES = YES;
227+
CLANG_WARN_SUSPICIOUS_MOVE = YES;
228+
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
229+
CLANG_WARN_UNREACHABLE_CODE = YES;
230+
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
231+
COPY_PHASE_STRIP = NO;
232+
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
233+
ENABLE_NS_ASSERTIONS = NO;
234+
ENABLE_STRICT_OBJC_MSGSEND = YES;
235+
ENABLE_USER_SCRIPT_SANDBOXING = YES;
236+
GCC_C_LANGUAGE_STANDARD = gnu17;
237+
GCC_NO_COMMON_BLOCKS = YES;
238+
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
239+
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
240+
GCC_WARN_UNDECLARED_SELECTOR = YES;
241+
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
242+
GCC_WARN_UNUSED_FUNCTION = YES;
243+
GCC_WARN_UNUSED_VARIABLE = YES;
244+
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
245+
MTL_ENABLE_DEBUG_INFO = NO;
246+
MTL_FAST_MATH = YES;
247+
SWIFT_COMPILATION_MODE = wholemodule;
248+
};
249+
name = Release;
250+
};
251+
4C23D0ED2F5DFFE800666984 /* Debug */ = {
252+
isa = XCBuildConfiguration;
253+
buildSettings = {
254+
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
255+
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
256+
CODE_SIGN_STYLE = Automatic;
257+
CURRENT_PROJECT_VERSION = 1;
258+
ENABLE_APP_SANDBOX = YES;
259+
ENABLE_PREVIEWS = YES;
260+
ENABLE_USER_SELECTED_FILES = readonly;
261+
GENERATE_INFOPLIST_FILE = YES;
262+
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
263+
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
264+
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
265+
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
266+
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
267+
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
268+
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
269+
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
270+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
271+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
272+
IPHONEOS_DEPLOYMENT_TARGET = 26.2;
273+
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
274+
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
275+
MACOSX_DEPLOYMENT_TARGET = 26.2;
276+
MARKETING_VERSION = 1.0;
277+
PRODUCT_BUNDLE_IDENTIFIER = devkit.DevConfiguration.ExampleApp;
278+
PRODUCT_NAME = "$(TARGET_NAME)";
279+
REGISTER_APP_GROUPS = YES;
280+
SDKROOT = auto;
281+
STRING_CATALOG_GENERATE_SYMBOLS = YES;
282+
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator";
283+
SWIFT_EMIT_LOC_STRINGS = YES;
284+
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
285+
SWIFT_VERSION = 5.0;
286+
TARGETED_DEVICE_FAMILY = "1,2,7";
287+
XROS_DEPLOYMENT_TARGET = 26.2;
288+
};
289+
name = Debug;
290+
};
291+
4C23D0EE2F5DFFE800666984 /* Release */ = {
292+
isa = XCBuildConfiguration;
293+
buildSettings = {
294+
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
295+
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
296+
CODE_SIGN_STYLE = Automatic;
297+
CURRENT_PROJECT_VERSION = 1;
298+
ENABLE_APP_SANDBOX = YES;
299+
ENABLE_PREVIEWS = YES;
300+
ENABLE_USER_SELECTED_FILES = readonly;
301+
GENERATE_INFOPLIST_FILE = YES;
302+
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
303+
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
304+
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
305+
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
306+
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
307+
"INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
308+
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
309+
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
310+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
311+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
312+
IPHONEOS_DEPLOYMENT_TARGET = 26.2;
313+
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
314+
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
315+
MACOSX_DEPLOYMENT_TARGET = 26.2;
316+
MARKETING_VERSION = 1.0;
317+
PRODUCT_BUNDLE_IDENTIFIER = devkit.DevConfiguration.ExampleApp;
318+
PRODUCT_NAME = "$(TARGET_NAME)";
319+
REGISTER_APP_GROUPS = YES;
320+
SDKROOT = auto;
321+
STRING_CATALOG_GENERATE_SYMBOLS = YES;
322+
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator";
323+
SWIFT_EMIT_LOC_STRINGS = YES;
324+
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
325+
SWIFT_VERSION = 5.0;
326+
TARGETED_DEVICE_FAMILY = "1,2,7";
327+
XROS_DEPLOYMENT_TARGET = 26.2;
328+
};
329+
name = Release;
330+
};
331+
/* End XCBuildConfiguration section */
332+
333+
/* Begin XCConfigurationList section */
334+
4C23D0DC2F5DFFE700666984 /* Build configuration list for PBXProject "App" */ = {
335+
isa = XCConfigurationList;
336+
buildConfigurations = (
337+
4C23D0EA2F5DFFE800666984 /* Debug */,
338+
4C23D0EB2F5DFFE800666984 /* Release */,
339+
);
340+
defaultConfigurationIsVisible = 0;
341+
defaultConfigurationName = Release;
342+
};
343+
4C23D0EC2F5DFFE800666984 /* Build configuration list for PBXNativeTarget "ExampleApp" */ = {
344+
isa = XCConfigurationList;
345+
buildConfigurations = (
346+
4C23D0ED2F5DFFE800666984 /* Debug */,
347+
4C23D0EE2F5DFFE800666984 /* Release */,
348+
);
349+
defaultConfigurationIsVisible = 0;
350+
defaultConfigurationName = Release;
351+
};
352+
/* End XCConfigurationList section */
353+
354+
/* Begin XCLocalSwiftPackageReference section */
355+
4C23D0F32F5E005000666984 /* XCLocalSwiftPackageReference "../../DevConfiguration" */ = {
356+
isa = XCLocalSwiftPackageReference;
357+
relativePath = ../../DevConfiguration;
358+
};
359+
/* End XCLocalSwiftPackageReference section */
360+
361+
/* Begin XCSwiftPackageProductDependency section */
362+
4C23D0F42F5E005000666984 /* DevConfiguration */ = {
363+
isa = XCSwiftPackageProductDependency;
364+
productName = DevConfiguration;
365+
};
366+
/* End XCSwiftPackageProductDependency section */
367+
};
368+
rootObject = 4C23D0D92F5DFFE700666984 /* Project object */;
369+
}

App/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)