@@ -180,29 +180,56 @@ private struct ProjectGitStatusSnapshot: Equatable {
180180 }
181181}
182182
183- @MainActor
184- private final class ProjectTreeActions {
183+ private final class ProjectTreeActions : @unchecked Sendable {
185184 private let model : AppModel
186185
187186 init ( model: AppModel ) {
188187 self . model = model
189188 }
190189
191- func openFile( _ url: URL ) { model. openFile ( url) }
192- func requestCreateFile( in url: URL ) { model. requestCreateFile ( in: url) }
193- func requestCreateDirectory( in url: URL ) { model. requestCreateDirectory ( in: url) }
194- func revealInFinder( _ url: URL ) { model. revealProjectItemInFinder ( url) }
195- func copyPath( _ url: URL , relative: Bool ) { model. copyProjectItemPath ( url, relative: relative) }
196- func duplicate( _ url: URL ) async { await model. duplicateProjectItem ( at: url) }
197- func requestRename( _ url: URL ) { model. requestRenameProjectItem ( at: url) }
198- func requestDelete( _ url: URL , isDirectory: Bool ) {
199- model. requestDeleteProjectItem ( at: url, isDirectory: isDirectory)
200- }
201- func refreshWorkspace( ) async { await model. refreshWorkspace ( ) }
202- func showGitDirectoryDiff( _ url: URL ) async { await model. showGitDirectoryDiff ( for: url) }
203- func selectChange( _ change: GitChange ) { model. selectChange ( change) }
204- func showLocalHistory( _ url: URL ) { model. showLocalHistory ( for: url) }
205- func javaIconKind( for url: URL ) async -> LitheIconKind ? { await model. javaIconKind ( for: url) }
190+ // Button and context-menu closures are not MainActor-isolated under the
191+ // Swift 6 test/release check. Keep these methods synchronous and hop.
192+ nonisolated func openFile( _ url: URL ) {
193+ Task { @MainActor in self . model. openFile ( url) }
194+ }
195+ nonisolated func requestCreateFile( _ url: URL ) {
196+ Task { @MainActor in self . model. requestCreateFile ( in: url) }
197+ }
198+ nonisolated func requestCreateDirectory( _ url: URL ) {
199+ Task { @MainActor in self . model. requestCreateDirectory ( in: url) }
200+ }
201+ nonisolated func revealInFinder( _ url: URL ) {
202+ Task { @MainActor in self . model. revealProjectItemInFinder ( url) }
203+ }
204+ nonisolated func copyPath( _ url: URL , relative: Bool ) {
205+ Task { @MainActor in self . model. copyProjectItemPath ( url, relative: relative) }
206+ }
207+ nonisolated func duplicate( _ url: URL ) {
208+ Task { await self . model. duplicateProjectItem ( at: url) }
209+ }
210+ nonisolated func requestRename( _ url: URL ) {
211+ Task { @MainActor in self . model. requestRenameProjectItem ( at: url) }
212+ }
213+ nonisolated func requestDelete( _ url: URL , _ isDirectory: Bool ) {
214+ Task { @MainActor in
215+ self . model. requestDeleteProjectItem ( at: url, isDirectory: isDirectory)
216+ }
217+ }
218+ nonisolated func refreshWorkspace( ) {
219+ Task { await self . model. refreshWorkspace ( ) }
220+ }
221+ nonisolated func showGitDirectoryDiff( _ url: URL ) {
222+ Task { await self . model. showGitDirectoryDiff ( for: url) }
223+ }
224+ nonisolated func selectChange( _ change: GitChange ) {
225+ Task { @MainActor in self . model. selectChange ( change) }
226+ }
227+ nonisolated func showLocalHistory( _ url: URL ) {
228+ Task { @MainActor in self . model. showLocalHistory ( for: url) }
229+ }
230+ func javaIconKind( _ url: URL ) async -> LitheIconKind ? {
231+ await model. javaIconKind ( for: url)
232+ }
206233}
207234
208235private struct ProjectFileTreeContent : View , Equatable {
@@ -361,24 +388,24 @@ private struct FileNodeRow: View {
361388 . contextMenu { fileContextMenu }
362389 . task ( id: node. url. standardizedFileURL. path) {
363390 guard node. url. pathExtension. lowercased ( ) == " java " else { return }
364- resolvedJavaIconKind = await actions. javaIconKind ( for : node. url)
391+ resolvedJavaIconKind = await actions. javaIconKind ( node. url)
365392 }
366393 }
367394
368395 @ViewBuilder
369396 private var directoryContextMenu : some View {
370397 if gitStatus. kind ( for: node. url, isDirectory: true ) != nil {
371398 Button ( " Show Git Diff " ) {
372- Task { await actions. showGitDirectoryDiff ( node. url) }
399+ actions. showGitDirectoryDiff ( node. url)
373400 }
374401 Divider ( )
375402 }
376403
377404 Button ( " New File… " ) {
378- actions. requestCreateFile ( in : node. url)
405+ actions. requestCreateFile ( node. url)
379406 }
380407 Button ( " New Directory… " ) {
381- actions. requestCreateDirectory ( in : node. url)
408+ actions. requestCreateDirectory ( node. url)
382409 }
383410
384411 Divider ( )
@@ -397,20 +424,20 @@ private struct FileNodeRow: View {
397424 Divider ( )
398425
399426 Button ( " Duplicate " ) {
400- Task { await actions. duplicate ( node. url) }
427+ actions. duplicate ( node. url)
401428 }
402429 Button ( " Rename… " ) {
403430 actions. requestRename ( node. url)
404431 }
405432 Button ( " Move to Trash " , role: . destructive) {
406- actions. requestDelete ( node. url, isDirectory : true )
433+ actions. requestDelete ( node. url, true )
407434 }
408435 }
409436
410437 Divider ( )
411438
412439 Button ( " Refresh " ) {
413- Task { await actions. refreshWorkspace ( ) }
440+ actions. refreshWorkspace ( )
414441 }
415442 }
416443
@@ -432,7 +459,7 @@ private struct FileNodeRow: View {
432459
433460 Group {
434461 Button ( " Duplicate " ) {
435- Task { await actions. duplicate ( node. url) }
462+ actions. duplicate ( node. url)
436463 }
437464 Button ( " Rename… " ) {
438465 actions. requestRename ( node. url)
@@ -441,7 +468,7 @@ private struct FileNodeRow: View {
441468 actions. showLocalHistory ( node. url)
442469 }
443470 Button ( " Move to Trash " , role: . destructive) {
444- actions. requestDelete ( node. url, isDirectory : false )
471+ actions. requestDelete ( node. url, false )
445472 }
446473 }
447474
0 commit comments