← All repositories

listless

A simple list app for Apple platforms

git clone https://code.inqk.net/listless.git


commit 27d3568ac9b8a0a47f8631d56718514aa270458b
parent 9d81e0ddac30910a5663550667ca43b8ae49d19a
Author: Michael Camilleri <[email protected]>
Date:   Sun,  8 Feb 2026 13:48:47 +0900

Make toolbar Mac only

Co-Authored-By: Claude 4.5 Sonnet <[email protected]>

Diffstat

MListless.xcodeproj/project.pbxproj | 45+++++++++++++++++++++++++--------------------
MListless.xcodeproj/xcshareddata/xcschemes/Listless iOS.xcscheme | 16++++++++++++----
MListless.xcodeproj/xcshareddata/xcschemes/Listless macOS.xcscheme | 14++++++++++----
MListless/Views/TaskListView.swift | 47++++++++++++++---------------------------------
AListlessMac/Views/TaskListView+Toolbar.swift | 44++++++++++++++++++++++++++++++++++++++++++++
AListlessiOS/Views/TaskListView+Toolbar.swift | 10++++++++++

6 files changed, 115 insertions(+), 61 deletions(-)

diff --git a/Listless.xcodeproj/project.pbxproj b/Listless.xcodeproj/project.pbxproj

@@ -3,10 +3,11 @@
 	archiveVersion = 1;
 	classes = {
 	};
-	objectVersion = 63;
+	objectVersion = 77;
 	objects = {
 
 /* Begin PBXBuildFile section */
+		074A81D9DAF58E8E088CBC89 /* TaskListView+Toolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431B0EA72D590AF0CC868515 /* TaskListView+Toolbar.swift */; };
 		0ACA67F6578EFF181EE5C9A7 /* TaskItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBB8A3BEB346267B30B4675F /* TaskItem.swift */; };
 		0BB5D2C4FADE3F1E22202814 /* ColorExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 917597025B3D5D18E33982D3 /* ColorExtensions.swift */; };
 		15B71073767FB4766A6BA2BE /* HoverCursorModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41D6E0CED14D79F31C45062 /* HoverCursorModifier.swift */; };
@@ -34,6 +35,7 @@
 		D6B3DBDD6A3F0A6E166CFFD5 /* TaskRowDragGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B3D0B4710C7A0EE4F227851 /* TaskRowDragGesture.swift */; };
 		D878CD3A552C6A9685A30AA8 /* PlatformTextFieldWidthModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF6B0195EA0176B72DE9B092 /* PlatformTextFieldWidthModifier.swift */; };
 		D8EFF49E9156083D675D47F0 /* KeyboardNavigationModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7B37EF6A2389656D105FF8 /* KeyboardNavigationModifier.swift */; };
+		D9DA553485AD0CA28D5BE0C8 /* TaskListView+Toolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93FF5B9F5B979D54D5DEE192 /* TaskListView+Toolbar.swift */; };
 		DC71C45D92524C3893BF9FDB /* PlatformTextFieldWidthModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81880970CCFC2CB00B65047E /* PlatformTextFieldWidthModifier.swift */; };
 		DC73A39A269AB495BCE1AC48 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C14858BDFD1FD5119F1F24A6 /* PersistenceController.swift */; };
 		ECD5E7EA05AE1C00B38C939E /* TaskStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 967F7ECEB3915CEDCE584872 /* TaskStoreTests.swift */; };
@@ -57,25 +59,27 @@
 		01E141436176F83594E2F26B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
 		0E7B37EF6A2389656D105FF8 /* KeyboardNavigationModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardNavigationModifier.swift; sourceTree = "<group>"; };
 		0F2BB7ABCABA4EB67180A200 /* ClickableTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClickableTextField.swift; sourceTree = "<group>"; };
-		126108860D7878DDC3BECC4B /* Listless iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Listless iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+		126108860D7878DDC3BECC4B /* Listless iOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "Listless iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		138612F350ECE29526F689B9 /* TaskRowDragGesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskRowDragGesture.swift; sourceTree = "<group>"; };
 		1B3D0B4710C7A0EE4F227851 /* TaskRowDragGesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskRowDragGesture.swift; sourceTree = "<group>"; };
 		1DA467DF2E59BDBE6EEF6A7D /* ListlessMacApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListlessMacApp.swift; sourceTree = "<group>"; };
 		2D3A2DDCE24E54ABCCFBBD4C /* TaskStoreOrderingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskStoreOrderingTests.swift; sourceTree = "<group>"; };
 		3313FEDB101EECA4B344EEF4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+		431B0EA72D590AF0CC868515 /* TaskListView+Toolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TaskListView+Toolbar.swift"; sourceTree = "<group>"; };
 		48AE1AE43296C1692FA6F755 /* PlatformScrollIndicatorsModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformScrollIndicatorsModifier.swift; sourceTree = "<group>"; };
-		4FC64B9F9370041BEDBD1E14 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
+		4FC64B9F9370041BEDBD1E14 /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = "<group>"; };
 		537A913AC421BAEF60D26D9C /* TaskListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskListView.swift; sourceTree = "<group>"; };
 		5B0E22B8F7B2B7283CAF749E /* Listless macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Listless macOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		5E88DDD119EEEECCD45F36D2 /* TaskStoreCompletionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskStoreCompletionTests.swift; sourceTree = "<group>"; };
-		74255E6B6C40899E9B17D927 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
+		74255E6B6C40899E9B17D927 /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = "<group>"; };
 		75B048B19C5219862BBED2E7 /* TestHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = "<group>"; };
 		7C73E9D4C42CCABBF0F33543 /* Listless.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Listless.entitlements; sourceTree = "<group>"; };
 		81880970CCFC2CB00B65047E /* PlatformTextFieldWidthModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformTextFieldWidthModifier.swift; sourceTree = "<group>"; };
 		82A3509AD32A54434BCC8017 /* HoverCursorModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoverCursorModifier.swift; sourceTree = "<group>"; };
 		917597025B3D5D18E33982D3 /* ColorExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtensions.swift; sourceTree = "<group>"; };
 		9262207DAC21619BD9EDEE15 /* Listless.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Listless.entitlements; sourceTree = "<group>"; };
-		944BAE054AAC1B9C4FC954F9 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
+		93FF5B9F5B979D54D5DEE192 /* TaskListView+Toolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TaskListView+Toolbar.swift"; sourceTree = "<group>"; };
+		944BAE054AAC1B9C4FC954F9 /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = "<group>"; };
 		967F7ECEB3915CEDCE584872 /* TaskStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskStoreTests.swift; sourceTree = "<group>"; };
 		97A08C589AB65ED2CB26A092 /* ClickableTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClickableTextField.swift; sourceTree = "<group>"; };
 		9B2BBE01D99CDA278BCB9F49 /* TaskStoreEdgeCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskStoreEdgeCaseTests.swift; sourceTree = "<group>"; };
@@ -84,10 +88,10 @@
 		B4D74AE2501F35974F57D21F /* PlatformScrollIndicatorsModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformScrollIndicatorsModifier.swift; sourceTree = "<group>"; };
 		BBDF292392702661DBB94D06 /* ColorExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtensions.swift; sourceTree = "<group>"; };
 		C14858BDFD1FD5119F1F24A6 /* PersistenceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceController.swift; sourceTree = "<group>"; };
-		C71466C5CD1A5BA984352F8D /* Listless iOS Unit Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Listless iOS Unit Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
-		C9B14DC786A336008AAB78EE /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
-		D10B5491A53E77C80F8F75CD /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
-		D123BB181208FC825777B0A7 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
+		C71466C5CD1A5BA984352F8D /* Listless iOS Unit Tests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = "Listless iOS Unit Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+		C9B14DC786A336008AAB78EE /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = "<group>"; };
+		D10B5491A53E77C80F8F75CD /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = "<group>"; };
+		D123BB181208FC825777B0A7 /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = "<group>"; };
 		D41D6E0CED14D79F31C45062 /* HoverCursorModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoverCursorModifier.swift; sourceTree = "<group>"; };
 		DC3DEE364304587D280C5672 /* TaskStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskStore.swift; sourceTree = "<group>"; };
 		EF6B0195EA0176B72DE9B092 /* PlatformTextFieldWidthModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformTextFieldWidthModifier.swift; sourceTree = "<group>"; };
@@ -134,6 +138,7 @@
 				82A3509AD32A54434BCC8017 /* HoverCursorModifier.swift */,
 				48AE1AE43296C1692FA6F755 /* PlatformScrollIndicatorsModifier.swift */,
 				81880970CCFC2CB00B65047E /* PlatformTextFieldWidthModifier.swift */,
+				93FF5B9F5B979D54D5DEE192 /* TaskListView+Toolbar.swift */,
 				1B3D0B4710C7A0EE4F227851 /* TaskRowDragGesture.swift */,
 			);
 			path = Views;
@@ -177,6 +182,7 @@
 				D41D6E0CED14D79F31C45062 /* HoverCursorModifier.swift */,
 				B4D74AE2501F35974F57D21F /* PlatformScrollIndicatorsModifier.swift */,
 				EF6B0195EA0176B72DE9B092 /* PlatformTextFieldWidthModifier.swift */,
+				431B0EA72D590AF0CC868515 /* TaskListView+Toolbar.swift */,
 				138612F350ECE29526F689B9 /* TaskRowDragGesture.swift */,
 			);
 			path = Views;
@@ -300,7 +306,7 @@
 			isa = PBXProject;
 			attributes = {
 				BuildIndependentTargetsInParallel = YES;
-				LastUpgradeCheck = 2620;
+				LastUpgradeCheck = 1430;
 				TargetAttributes = {
 					0FB4F07A37999BBC6DFE4DBB = {
 						DevelopmentTeam = 7TD7PZBNXP;
@@ -326,6 +332,7 @@
 			);
 			mainGroup = ED4862258A8A70025EE14416;
 			minimizedProjectReferenceProxies = 1;
+			preferredProjectObjectVersion = 77;
 			projectDirPath = "";
 			projectRoot = "";
 			targets = (
@@ -351,6 +358,7 @@
 				A8D13DD6196772ECA146CF2A /* PlatformScrollIndicatorsModifier.swift in Sources */,
 				D878CD3A552C6A9685A30AA8 /* PlatformTextFieldWidthModifier.swift in Sources */,
 				C1FE091454864C4BBBBEB077 /* TaskItem.swift in Sources */,
+				074A81D9DAF58E8E088CBC89 /* TaskListView+Toolbar.swift in Sources */,
 				8E08F4C82D6F9E67667CB20A /* TaskListView.swift in Sources */,
 				C1BD61D6DFA687E9CB9ACA60 /* TaskRowDragGesture.swift in Sources */,
 				C2400278D5F6F79C85A68897 /* TaskRowView.swift in Sources */,
@@ -372,6 +380,7 @@
 				8E680EC18B0339931E785F0C /* PlatformScrollIndicatorsModifier.swift in Sources */,
 				DC71C45D92524C3893BF9FDB /* PlatformTextFieldWidthModifier.swift in Sources */,
 				0ACA67F6578EFF181EE5C9A7 /* TaskItem.swift in Sources */,
+				D9DA553485AD0CA28D5BE0C8 /* TaskListView+Toolbar.swift in Sources */,
 				42E4CDE1D17463554CC4F41F /* TaskListView.swift in Sources */,
 				D6B3DBDD6A3F0A6E166CFFD5 /* TaskRowDragGesture.swift in Sources */,
 				9041B7CED5298439BF7DC2C1 /* TaskRowView.swift in Sources */,
@@ -409,7 +418,7 @@
 				CODE_SIGN_ENTITLEMENTS = ListlessMac/Listless.entitlements;
 				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
-				DEAD_CODE_STRIPPING = YES;
+				DEVELOPMENT_TEAM = 7TD7PZBNXP;
 				INFOPLIST_FILE = ListlessMac/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
@@ -427,7 +436,7 @@
 				CODE_SIGN_ENTITLEMENTS = ListlessMac/Listless.entitlements;
 				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
-				DEAD_CODE_STRIPPING = YES;
+				DEVELOPMENT_TEAM = 7TD7PZBNXP;
 				INFOPLIST_FILE = ListlessMac/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
@@ -472,12 +481,9 @@
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
-				DEAD_CODE_STRIPPING = YES;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-				DEVELOPMENT_TEAM = 7TD7PZBNXP;
 				ENABLE_NS_ASSERTIONS = NO;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
-				ENABLE_USER_SCRIPT_SANDBOXING = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu11;
 				GCC_NO_COMMON_BLOCKS = YES;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -491,7 +497,6 @@
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_FAST_MATH = YES;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				STRING_CATALOG_GENERATE_SYMBOLS = YES;
 				SWIFT_COMPILATION_MODE = wholemodule;
 				SWIFT_OPTIMIZATION_LEVEL = "-O";
 				SWIFT_VERSION = 6;
@@ -503,6 +508,7 @@
 			buildSettings = {
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
+				DEVELOPMENT_TEAM = 7TD7PZBNXP;
 				GENERATE_INFOPLIST_FILE = YES;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
@@ -550,12 +556,9 @@
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
-				DEAD_CODE_STRIPPING = YES;
 				DEBUG_INFORMATION_FORMAT = dwarf;
-				DEVELOPMENT_TEAM = 7TD7PZBNXP;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
-				ENABLE_USER_SCRIPT_SANDBOXING = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu11;
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_NO_COMMON_BLOCKS = YES;
@@ -576,7 +579,6 @@
 				MTL_FAST_MATH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				STRING_CATALOG_GENERATE_SYMBOLS = YES;
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 6;
@@ -590,6 +592,7 @@
 				CODE_SIGN_ENTITLEMENTS = ListlessiOS/Listless.entitlements;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				CODE_SIGN_STYLE = Automatic;
+				DEVELOPMENT_TEAM = 7TD7PZBNXP;
 				INFOPLIST_FILE = ListlessiOS/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
@@ -606,6 +609,7 @@
 			buildSettings = {
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
+				DEVELOPMENT_TEAM = 7TD7PZBNXP;
 				GENERATE_INFOPLIST_FILE = YES;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
@@ -626,6 +630,7 @@
 				CODE_SIGN_ENTITLEMENTS = ListlessiOS/Listless.entitlements;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				CODE_SIGN_STYLE = Automatic;
+				DEVELOPMENT_TEAM = 7TD7PZBNXP;
 				INFOPLIST_FILE = ListlessiOS/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",

diff --git a/Listless.xcodeproj/xcshareddata/xcschemes/Listless iOS.xcscheme b/Listless.xcodeproj/xcshareddata/xcschemes/Listless iOS.xcscheme

@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "2620"
-   version = "1.3">
+   LastUpgradeVersion = "1430"
+   version = "1.7">
    <BuildAction
       parallelizeBuildables = "YES"
-      buildImplicitDependencies = "YES">
+      buildImplicitDependencies = "YES"
+      runPostActionsOnFailure = "NO">
       <BuildActionEntries>
          <BuildActionEntry
             buildForTesting = "YES"
@@ -26,7 +27,8 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      onlyGenerateCoverageForSpecifiedTargets = "NO">
       <MacroExpansion>
          <BuildableReference
             BuildableIdentifier = "primary"
@@ -50,6 +52,8 @@
             </BuildableReference>
          </TestableReference>
       </Testables>
+      <CommandLineArguments>
+      </CommandLineArguments>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -71,6 +75,8 @@
             ReferencedContainer = "container:Listless.xcodeproj">
          </BuildableReference>
       </BuildableProductRunnable>
+      <CommandLineArguments>
+      </CommandLineArguments>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
@@ -88,6 +94,8 @@
             ReferencedContainer = "container:Listless.xcodeproj">
          </BuildableReference>
       </BuildableProductRunnable>
+      <CommandLineArguments>
+      </CommandLineArguments>
    </ProfileAction>
    <AnalyzeAction
       buildConfiguration = "Debug">

diff --git a/Listless.xcodeproj/xcshareddata/xcschemes/Listless macOS.xcscheme b/Listless.xcodeproj/xcshareddata/xcschemes/Listless macOS.xcscheme

@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "2620"
-   version = "1.3">
+   LastUpgradeVersion = "1430"
+   version = "1.7">
    <BuildAction
       parallelizeBuildables = "YES"
-      buildImplicitDependencies = "YES">
+      buildImplicitDependencies = "YES"
+      runPostActionsOnFailure = "NO">
       <BuildActionEntries>
          <BuildActionEntry
             buildForTesting = "YES"
@@ -26,7 +27,8 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      onlyGenerateCoverageForSpecifiedTargets = "NO">
       <MacroExpansion>
          <BuildableReference
             BuildableIdentifier = "primary"
@@ -59,6 +61,8 @@
             ReferencedContainer = "container:Listless.xcodeproj">
          </BuildableReference>
       </BuildableProductRunnable>
+      <CommandLineArguments>
+      </CommandLineArguments>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
@@ -76,6 +80,8 @@
             ReferencedContainer = "container:Listless.xcodeproj">
          </BuildableReference>
       </BuildableProductRunnable>
+      <CommandLineArguments>
+      </CommandLineArguments>
    </ProfileAction>
    <AnalyzeAction
       buildConfiguration = "Debug">

diff --git a/Listless/Views/TaskListView.swift b/Listless/Views/TaskListView.swift

@@ -18,8 +18,8 @@ struct TaskListView: View {
         animation: .default
     )
     private var tasks: FetchedResults<TaskItem>
-    @FocusState private var focusedField: FocusField?
-    @State private var selectedTaskID: UUID?
+    @FocusState var focusedField: FocusField?
+    @State var selectedTaskID: UUID?
     @State private var refreshID = UUID()
     @State private var draggedTaskID: UUID?
     @State private var visualOrder: [UUID]?
@@ -165,33 +165,7 @@ struct TaskListView: View {
             managedObjectContext.undoManager = newValue
         }
         .toolbar {
-            ToolbarItem(placement: .automatic) {
-                Spacer()
-            }
-
-            ToolbarItem(placement: .automatic) {
-                Button {
-                    createTaskAndFocus()
-                    // Trigger focus resolution by setting to nil
-                    focusedField = nil
-                } label: {
-                    Label("New Task", systemImage: "plus")
-                }
-                .help("Create a new task")
-            }
-
-            ToolbarItem(placement: .automatic) {
-                Button {
-                    if let currentID = selectedTaskID,
-                       let task = allTasksInDisplayOrder.first(where: { $0.id == currentID }) {
-                        deleteTask(task)
-                    }
-                } label: {
-                    Label("Delete", systemImage: "trash")
-                }
-                .disabled(selectedTaskID == nil)
-                .help("Delete selected task")
-            }
+            platformToolbar
         }
     }
 
@@ -210,12 +184,12 @@ struct TaskListView: View {
         }
     }
 
-    private var completedTasks: [TaskItem] {
+    var completedTasks: [TaskItem] {
         Array(tasks.filter { $0.isCompleted })
             .sorted { $0.updatedAt > $1.updatedAt }
     }
 
-    private var allTasksInDisplayOrder: [TaskItem] {
+    var allTasksInDisplayOrder: [TaskItem] {
         displayActiveTasks + completedTasks
     }
 
@@ -231,7 +205,7 @@ struct TaskListView: View {
         return lastTask.id == taskID
     }
 
-    private func createTaskAndFocus() {
+    func createTaskAndFocus() {
         // Clear any lingering drag state
         draggedTaskID = nil
         visualOrder = nil
@@ -318,7 +292,7 @@ struct TaskListView: View {
         selectedTaskID = taskID
     }
 
-    private func deleteTask(_ task: TaskItem) {
+    func deleteTask(_ task: TaskItem) {
         let taskID = task.id
         print("🔴 deleteTask() called for task \(taskID)")
 
@@ -332,6 +306,13 @@ struct TaskListView: View {
         print("🔴 deleteTask() completed")
     }
 
+    func clearCompletedTasks() {
+        // Delete all completed tasks (in reverse to avoid index issues)
+        for task in completedTasks.reversed() {
+            store.delete(taskID: task.id)
+        }
+    }
+
     private func navigateUp() -> KeyPress.Result {
         print("⬆️ navigateUp() called, focusedField: \(String(describing: focusedField))")
         guard focusedField == .scrollView else {

diff --git a/ListlessMac/Views/TaskListView+Toolbar.swift b/ListlessMac/Views/TaskListView+Toolbar.swift

@@ -0,0 +1,44 @@
+import SwiftUI
+
+extension TaskListView {
+    @ToolbarContentBuilder
+    var platformToolbar: some ToolbarContent {
+        ToolbarItem(placement: .automatic) {
+            Spacer()
+        }
+
+        ToolbarItemGroup(placement: .automatic) {
+            HStack {
+                Button {
+                    createTaskAndFocus()
+                    // Trigger focus resolution by setting to nil
+                    focusedField = nil
+                } label: {
+                    Label("New Task", systemImage: "plus")
+                }
+                .help("Create a new task")
+
+                Button {
+                    if let currentID = selectedTaskID,
+                       let task = allTasksInDisplayOrder.first(where: { $0.id == currentID }) {
+                        deleteTask(task)
+                    }
+                } label: {
+                    Label("Delete", systemImage: "trash")
+                }
+                .disabled(selectedTaskID == nil)
+                .help("Delete selected task")
+
+                Divider()
+
+                Button {
+                    clearCompletedTasks()
+                } label: {
+                    Label("Clear Completed", systemImage: "tray")
+                }
+                .disabled(completedTasks.isEmpty)
+                .help("Clear all completed tasks")
+            }
+        }
+    }
+}

diff --git a/ListlessiOS/Views/TaskListView+Toolbar.swift b/ListlessiOS/Views/TaskListView+Toolbar.swift

@@ -0,0 +1,10 @@
+import SwiftUI
+
+extension TaskListView {
+    @ToolbarContentBuilder
+    var platformToolbar: some ToolbarContent {
+        // No toolbar on iOS - users interact with tasks directly
+        // (tap to toggle, swipe to delete, tap background to create)
+        ToolbarItemGroup {}
+    }
+}