diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index a00ba8740..45913944a 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -13,7 +13,7 @@ 043C321627E3201F006AE443 /* WorkspaceDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043C321527E3201F006AE443 /* WorkspaceDocument.swift */; }; 04540D5E27DD08C300E91B77 /* WorkspaceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B658FB3127DA9E0F00EA4DBD /* WorkspaceView.swift */; }; 04660F6A27E51E5C00477777 /* CodeEditWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04660F6927E51E5C00477777 /* CodeEditWindowController.swift */; }; - 0485EB1F27E7458B00138301 /* WorkspaceCodeFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0485EB1E27E7458B00138301 /* WorkspaceCodeFileView.swift */; }; + 0485EB1F27E7458B00138301 /* EditorAreaFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0485EB1E27E7458B00138301 /* EditorAreaFileView.swift */; }; 04BA7C0B2AE2A2D100584E1C /* GitBranch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BA7C0A2AE2A2D100584E1C /* GitBranch.swift */; }; 04BA7C0E2AE2A76E00584E1C /* SourceControlNavigatorChangesCommitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BA7C0D2AE2A76E00584E1C /* SourceControlNavigatorChangesCommitView.swift */; }; 04BA7C132AE2AA7300584E1C /* GitCheckoutBranchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BA7C112AE2AA7300584E1C /* GitCheckoutBranchViewModel.swift */; }; @@ -115,8 +115,6 @@ 58798238292E30B90085B254 /* FeedbackWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58798232292E30B90085B254 /* FeedbackWindowController.swift */; }; 5879824F292E78D80085B254 /* CodeFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58798248292E78D80085B254 /* CodeFileView.swift */; }; 58798250292E78D80085B254 /* CodeFileDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58798249292E78D80085B254 /* CodeFileDocument.swift */; }; - 58798251292E78D80085B254 /* OtherFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5879824B292E78D80085B254 /* OtherFileView.swift */; }; - 58798252292E78D80085B254 /* ImageFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5879824D292E78D80085B254 /* ImageFileView.swift */; }; 58798284292ED0FB0085B254 /* TerminalEmulatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58798280292ED0FB0085B254 /* TerminalEmulatorView.swift */; }; 58798285292ED0FB0085B254 /* TerminalEmulatorView+Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58798281292ED0FB0085B254 /* TerminalEmulatorView+Coordinator.swift */; }; 58798286292ED0FB0085B254 /* SwiftTerm+Color+Init.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58798283292ED0FB0085B254 /* SwiftTerm+Color+Init.swift */; }; @@ -285,6 +283,11 @@ 6195E3112B640485007261CA /* WorkspaceDocument+SearchState+IndexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6195E3102B640485007261CA /* WorkspaceDocument+SearchState+IndexTests.swift */; }; 61A53A7E2B4449870093BF8A /* WorkspaceDocument+Find.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A53A7D2B4449870093BF8A /* WorkspaceDocument+Find.swift */; }; 61A53A812B4449F00093BF8A /* WorkspaceDocument+Index.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61A53A802B4449F00093BF8A /* WorkspaceDocument+Index.swift */; }; + 661EF7B82BEE215300C3E577 /* ImageFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 661EF7B72BEE215300C3E577 /* ImageFileView.swift */; }; + 661EF7BD2BEE215300C3E577 /* LoadingFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 661EF7BC2BEE215300C3E577 /* LoadingFileView.swift */; }; + 669BC4082BED306400D1197C /* AnyFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669BC4072BED306400D1197C /* AnyFileView.swift */; }; + 66F2C8C42BEAA939004674F7 /* PDFFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2C8C32BEAA939004674F7 /* PDFFileView.swift */; }; + 66F370342BEE537B00D3B823 /* NonTextFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F370332BEE537B00D3B823 /* NonTextFileView.swift */; }; 6C049A372A49E2DB00D42923 /* DirectoryEventStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C049A362A49E2DB00D42923 /* DirectoryEventStream.swift */; }; 6C05A8AF284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C05A8AE284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift */; }; 6C0617D62BDB4432008C9C42 /* LogStream in Frameworks */ = {isa = PBXBuildFile; productRef = 6C0617D52BDB4432008C9C42 /* LogStream */; }; @@ -298,7 +301,7 @@ 6C147C4529A329350089B630 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 6C147C4429A329350089B630 /* OrderedCollections */; }; 6C147C4929A32A080089B630 /* EditorLayoutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C4829A32A080089B630 /* EditorLayoutView.swift */; }; 6C147C4B29A32A7B0089B630 /* Environment+SplitEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C4A29A32A7B0089B630 /* Environment+SplitEditor.swift */; }; - 6C147C4D29A32AA30089B630 /* EditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C4C29A32AA30089B630 /* EditorView.swift */; }; + 6C147C4D29A32AA30089B630 /* EditorAreaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C4C29A32AA30089B630 /* EditorAreaView.swift */; }; 6C14CEB028777D3C001468FE /* FindNavigatorListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C14CEAF28777D3C001468FE /* FindNavigatorListViewController.swift */; }; 6C14CEB32877A68F001468FE /* FindNavigatorMatchListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C14CEB22877A68F001468FE /* FindNavigatorMatchListCell.swift */; }; 6C18620A298BF5A800C663EA /* RecentProjectsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C186209298BF5A800C663EA /* RecentProjectsListView.swift */; }; @@ -395,7 +398,6 @@ 852E62012A5C17E500447138 /* PageAndSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852E62002A5C17E500447138 /* PageAndSettings.swift */; }; 85745D632A38F8D900089AAB /* String+HighlightOccurrences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85745D622A38F8D900089AAB /* String+HighlightOccurrences.swift */; }; 85773E1E2A3E0A1F00C5D926 /* SettingsSearchResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85773E1D2A3E0A1F00C5D926 /* SettingsSearchResult.swift */; }; - 85CD0C5F2A10CC3200E531FD /* URL+isImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85CD0C5E2A10CC3200E531FD /* URL+isImage.swift */; }; 85E4122A2A46C8CA00183F2B /* LocationsSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85E412292A46C8CA00183F2B /* LocationsSettings.swift */; }; 9D36E1BF2B5E7D7500443C41 /* GitBranchesGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D36E1BE2B5E7D7500443C41 /* GitBranchesGroup.swift */; }; B6041F4D29D7A4E9000F3454 /* SettingsPageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6041F4C29D7A4E9000F3454 /* SettingsPageView.swift */; }; @@ -573,7 +575,7 @@ 04660F6027E3A68A00477777 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 04660F6927E51E5C00477777 /* CodeEditWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeEditWindowController.swift; sourceTree = ""; }; 0468438427DC76E200F8E88E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 0485EB1E27E7458B00138301 /* WorkspaceCodeFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceCodeFileView.swift; sourceTree = ""; }; + 0485EB1E27E7458B00138301 /* EditorAreaFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorAreaFileView.swift; sourceTree = ""; }; 04BA7C0A2AE2A2D100584E1C /* GitBranch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitBranch.swift; sourceTree = ""; }; 04BA7C0D2AE2A76E00584E1C /* SourceControlNavigatorChangesCommitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceControlNavigatorChangesCommitView.swift; sourceTree = ""; }; 04BA7C112AE2AA7300584E1C /* GitCheckoutBranchViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitCheckoutBranchViewModel.swift; sourceTree = ""; }; @@ -678,8 +680,6 @@ 58798232292E30B90085B254 /* FeedbackWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedbackWindowController.swift; sourceTree = ""; }; 58798248292E78D80085B254 /* CodeFileView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodeFileView.swift; sourceTree = ""; }; 58798249292E78D80085B254 /* CodeFileDocument.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodeFileDocument.swift; sourceTree = ""; }; - 5879824B292E78D80085B254 /* OtherFileView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OtherFileView.swift; sourceTree = ""; }; - 5879824D292E78D80085B254 /* ImageFileView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageFileView.swift; sourceTree = ""; }; 58798280292ED0FB0085B254 /* TerminalEmulatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TerminalEmulatorView.swift; sourceTree = ""; }; 58798281292ED0FB0085B254 /* TerminalEmulatorView+Coordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TerminalEmulatorView+Coordinator.swift"; sourceTree = ""; }; 58798283292ED0FB0085B254 /* SwiftTerm+Color+Init.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftTerm+Color+Init.swift"; sourceTree = ""; }; @@ -848,6 +848,11 @@ 6195E3102B640485007261CA /* WorkspaceDocument+SearchState+IndexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+SearchState+IndexTests.swift"; sourceTree = ""; }; 61A53A7D2B4449870093BF8A /* WorkspaceDocument+Find.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+Find.swift"; sourceTree = ""; }; 61A53A802B4449F00093BF8A /* WorkspaceDocument+Index.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+Index.swift"; sourceTree = ""; }; + 661EF7B72BEE215300C3E577 /* ImageFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageFileView.swift; sourceTree = ""; }; + 661EF7BC2BEE215300C3E577 /* LoadingFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingFileView.swift; sourceTree = ""; }; + 669BC4072BED306400D1197C /* AnyFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyFileView.swift; sourceTree = ""; }; + 66F2C8C32BEAA939004674F7 /* PDFFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDFFileView.swift; sourceTree = ""; }; + 66F370332BEE537B00D3B823 /* NonTextFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonTextFileView.swift; sourceTree = ""; }; 6C049A362A49E2DB00D42923 /* DirectoryEventStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectoryEventStream.swift; sourceTree = ""; }; 6C05A8AE284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+Listeners.swift"; sourceTree = ""; }; 6C092ED92A53A58600489202 /* EditorLayout+StateRestoration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EditorLayout+StateRestoration.swift"; sourceTree = ""; }; @@ -858,7 +863,7 @@ 6C147C3F29A328560089B630 /* SplitViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitViewData.swift; sourceTree = ""; }; 6C147C4829A32A080089B630 /* EditorLayoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorLayoutView.swift; sourceTree = ""; }; 6C147C4A29A32A7B0089B630 /* Environment+SplitEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+SplitEditor.swift"; sourceTree = ""; }; - 6C147C4C29A32AA30089B630 /* EditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorView.swift; sourceTree = ""; }; + 6C147C4C29A32AA30089B630 /* EditorAreaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorAreaView.swift; sourceTree = ""; }; 6C14CEAF28777D3C001468FE /* FindNavigatorListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindNavigatorListViewController.swift; sourceTree = ""; }; 6C14CEB22877A68F001468FE /* FindNavigatorMatchListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindNavigatorMatchListCell.swift; sourceTree = ""; }; 6C186209298BF5A800C663EA /* RecentProjectsListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentProjectsListView.swift; sourceTree = ""; }; @@ -941,7 +946,6 @@ 852E62002A5C17E500447138 /* PageAndSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageAndSettings.swift; sourceTree = ""; }; 85745D622A38F8D900089AAB /* String+HighlightOccurrences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+HighlightOccurrences.swift"; sourceTree = ""; }; 85773E1D2A3E0A1F00C5D926 /* SettingsSearchResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSearchResult.swift; sourceTree = ""; }; - 85CD0C5E2A10CC3200E531FD /* URL+isImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+isImage.swift"; sourceTree = ""; }; 85E412292A46C8CA00183F2B /* LocationsSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationsSettings.swift; sourceTree = ""; }; 8B9A0E162B9FE84B007E2DBF /* Pre.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Pre.xcconfig; sourceTree = ""; }; 9D36E1BE2B5E7D7500443C41 /* GitBranchesGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitBranchesGroup.swift; sourceTree = ""; }; @@ -1109,7 +1113,8 @@ isa = PBXGroup; children = ( 5831E3CE2933F3DE00D5A6D2 /* Controllers */, - 5831E3CF2933F4E000D5A6D2 /* Views */, + 611191F82B08CC8000D4459B /* Indexer */, + 58798249292E78D80085B254 /* CodeFileDocument.swift */, 043C321527E3201F006AE443 /* WorkspaceDocument.swift */, 043BCF02281DA18A000AC47C /* WorkspaceDocument+SearchState.swift */, 61A53A802B4449F00093BF8A /* WorkspaceDocument+Index.swift */, @@ -1120,7 +1125,6 @@ 6C092EDF2A53BFCF00489202 /* WorkspaceStateKey.swift */, 61538B8F2B111FE800A88846 /* String+AppearancesOfSubstring.swift */, 61538B922B11201900A88846 /* String+Character.swift */, - 611191F82B08CC8000D4459B /* Indexer */, ); path = Documents; sourceTree = ""; @@ -1403,7 +1407,6 @@ 5878DA7D291862BC00DD95A3 /* Acknowledgements */, 588847642992A30900996D95 /* CEWorkspace */, 587B9D7529300ABD00AC7927 /* CodeEditUI */, - 58798244292E78D80085B254 /* CodeFile */, 58FD7603291EA1CB0051D6E4 /* Commands */, 284DC84B2978B5EB00BF2770 /* Contributors */, 043C321227E31FE8006AE443 /* Documents */, @@ -1496,14 +1499,6 @@ path = Controllers; sourceTree = ""; }; - 5831E3CF2933F4E000D5A6D2 /* Views */ = { - isa = PBXGroup; - children = ( - 0485EB1E27E7458B00138301 /* WorkspaceCodeFileView.swift */, - ); - path = Views; - sourceTree = ""; - }; 5831E3D02934036D00D5A6D2 /* NSTableView */ = { isa = PBXGroup; children = ( @@ -1697,34 +1692,6 @@ path = Controllers; sourceTree = ""; }; - 58798244292E78D80085B254 /* CodeFile */ = { - isa = PBXGroup; - children = ( - 5879824C292E78D80085B254 /* Image */, - 5879824A292E78D80085B254 /* Other */, - 58798249292E78D80085B254 /* CodeFileDocument.swift */, - 58798248292E78D80085B254 /* CodeFileView.swift */, - 6C5B63DD29C76213005454BA /* WindowCodeFileView.swift */, - ); - path = CodeFile; - sourceTree = ""; - }; - 5879824A292E78D80085B254 /* Other */ = { - isa = PBXGroup; - children = ( - 5879824B292E78D80085B254 /* OtherFileView.swift */, - ); - path = Other; - sourceTree = ""; - }; - 5879824C292E78D80085B254 /* Image */ = { - isa = PBXGroup; - children = ( - 5879824D292E78D80085B254 /* ImageFileView.swift */, - ); - path = Image; - sourceTree = ""; - }; 5879827E292ED0FB0085B254 /* TerminalEmulator */ = { isa = PBXGroup; children = ( @@ -2195,7 +2162,6 @@ 58D01C87293167DC00C5B6B4 /* Extensions */ = { isa = PBXGroup; children = ( - 85CD0C5D2A10CC2500E531FD /* URL */, 6C82D6C429C0129E00495C54 /* NSApplication */, 77A01E922BCA9C0400F0EA38 /* NSWindow */, 588847672992AAB800996D95 /* Array */, @@ -2464,6 +2430,7 @@ 6CAAF68F29BCC6F900A1F48A /* WindowCommands */ = { isa = PBXGroup; children = ( + 6C82D6BF29C00EE300495C54 /* Utils */, B66A4E5229C91831004573B4 /* CodeEditCommands.swift */, 6CFF967729BEBCF600182D6F /* MainCommands.swift */, 6CFF967529BEBCD900182D6F /* FileCommands.swift */, @@ -2473,7 +2440,6 @@ 6CFF967B29BEBD5200182D6F /* WindowCommands.swift */, 6C82D6B829BFE34900495C54 /* HelpCommands.swift */, 6C578D8B29CD372700DC73B2 /* ExtensionCommands.swift */, - 6C82D6BF29C00EE300495C54 /* Utils */, ); path = WindowCommands; sourceTree = ""; @@ -2526,14 +2492,6 @@ path = NSWindow; sourceTree = ""; }; - 85CD0C5D2A10CC2500E531FD /* URL */ = { - isa = PBXGroup; - children = ( - 85CD0C5E2A10CC3200E531FD /* URL+isImage.swift */, - ); - path = URL; - sourceTree = ""; - }; 85E412282A46C8B900183F2B /* Models */ = { isa = PBXGroup; children = ( @@ -2739,8 +2697,16 @@ B67660632AA970E300CD56B0 /* Views */ = { isa = PBXGroup; children = ( - 6C147C4C29A32AA30089B630 /* EditorView.swift */, + 669BC4072BED306400D1197C /* AnyFileView.swift */, + 58798248292E78D80085B254 /* CodeFileView.swift */, + 6C147C4C29A32AA30089B630 /* EditorAreaView.swift */, + 0485EB1E27E7458B00138301 /* EditorAreaFileView.swift */, 6C147C4829A32A080089B630 /* EditorLayoutView.swift */, + 661EF7BC2BEE215300C3E577 /* LoadingFileView.swift */, + 661EF7B72BEE215300C3E577 /* ImageFileView.swift */, + 66F370332BEE537B00D3B823 /* NonTextFileView.swift */, + 66F2C8C32BEAA939004674F7 /* PDFFileView.swift */, + 6C5B63DD29C76213005454BA /* WindowCodeFileView.swift */, ); path = Views; sourceTree = ""; @@ -3350,7 +3316,6 @@ B67DB0F92AFDF638002DC647 /* IconButtonStyle.swift in Sources */, 587B9E5E29301D8F00AC7927 /* GitLabCommitRouter.swift in Sources */, 58F2EB0D292FB2B0004A9BDE /* ThemeSettings.swift in Sources */, - 85CD0C5F2A10CC3200E531FD /* URL+isImage.swift in Sources */, 587B9D9F29300ABD00AC7927 /* SegmentedControl.swift in Sources */, 6C7256D729A3D7D000C2D3E0 /* SplitViewControllerView.swift in Sources */, B6EA1FE529DA33DB001BF195 /* ThemeModel.swift in Sources */, @@ -3362,6 +3327,7 @@ B6C4F2A62B3CABD200B2B140 /* HistoryInspectorItemView.swift in Sources */, B65B10FE2B08B07D002852CF /* SourceControlNavigatorChangesList.swift in Sources */, 58F2EB03292FB2B0004A9BDE /* Documentation.docc in Sources */, + 66F2C8C42BEAA939004674F7 /* PDFFileView.swift in Sources */, 611192042B08CCED00D4459B /* SearchIndexer+ProgressiveSearch.swift in Sources */, 611192022B08CCDC00D4459B /* SearchIndexer+Search.swift in Sources */, 04BA7C272AE2E9F100584E1C /* GitClient+Push.swift in Sources */, @@ -3409,6 +3375,7 @@ B6C4F2AC2B3CC4D000B2B140 /* CommitChangedFileListItemView.swift in Sources */, 6C82D6B329BFD88700495C54 /* NavigateCommands.swift in Sources */, B66A4E4C29C9179B004573B4 /* CodeEditApp.swift in Sources */, + 661EF7B82BEE215300C3E577 /* ImageFileView.swift in Sources */, 4E7F066629602E7B00BB3C12 /* CodeEditSplitViewController.swift in Sources */, 587B9E8D29301D8F00AC7927 /* GitHubAccount.swift in Sources */, 201169E72837B5CA00F92B46 /* SourceControlManager.swift in Sources */, @@ -3459,7 +3426,6 @@ 77A01E322BB4274B00F0EA38 /* TasksCEWorkspaceSettingsView.swift in Sources */, B6E41C8F29DE9CD80088F9F4 /* AccountsSettingsDetailsView.swift in Sources */, 5882252B292C280D00E83CDE /* StatusBarCursorLocationLabel.swift in Sources */, - 58798252292E78D80085B254 /* ImageFileView.swift in Sources */, 5882252D292C280D00E83CDE /* StatusBarSplitTerminalButton.swift in Sources */, 58798238292E30B90085B254 /* FeedbackWindowController.swift in Sources */, 587B9E6C29301D8F00AC7927 /* GitLabNamespace.swift in Sources */, @@ -3468,7 +3434,7 @@ 6CE6226B2A2A1C730013085C /* UtilityAreaTab.swift in Sources */, 587B9DA329300ABD00AC7927 /* SettingsTextEditor.swift in Sources */, B6F0517B29D9E46400D72287 /* SourceControlSettingsView.swift in Sources */, - 6C147C4D29A32AA30089B630 /* EditorView.swift in Sources */, + 6C147C4D29A32AA30089B630 /* EditorAreaView.swift in Sources */, B6152B802ADAE421004C6012 /* CodeEditWindowControllerExtensions.swift in Sources */, 587B9E7B29301D8F00AC7927 /* GitHubRouter.swift in Sources */, 201169E22837B3D800F92B46 /* SourceControlNavigatorChangesView.swift in Sources */, @@ -3488,6 +3454,7 @@ B6E55C3B2A95368E003ECC7D /* EditorTabsOverflowShadow.swift in Sources */, 58A5DFA229339F6400D1BD5D /* KeybindingManager.swift in Sources */, B62AEDB32A1FD95B009A9F52 /* UtilityAreaTerminalView.swift in Sources */, + 661EF7BD2BEE215300C3E577 /* LoadingFileView.swift in Sources */, 58AFAA2E2933C69E00482B53 /* EditorTabRepresentable.swift in Sources */, 6C4104E6297C884F00F472BA /* AboutDetailView.swift in Sources */, 6C6BD6F129CD13FA00235D17 /* ExtensionDiscovery.swift in Sources */, @@ -3499,6 +3466,7 @@ 6CABB1A129C5593800340467 /* SearchPanelView.swift in Sources */, D7211D4327E066CE008F2ED7 /* Localized+Ex.swift in Sources */, 581BFB692926431000D251EC /* WelcomeActionView.swift in Sources */, + 669BC4082BED306400D1197C /* AnyFileView.swift in Sources */, 20D839AE280E0CA700B27357 /* HistoryPopoverView.swift in Sources */, B6E41C7029DD157F0088F9F4 /* AccountsSettingsView.swift in Sources */, 6CFF967A29BEBD2400182D6F /* ViewCommands.swift in Sources */, @@ -3546,14 +3514,13 @@ 5879821A292D92370085B254 /* SearchResultModel.swift in Sources */, B6F0517729D9E3AD00D72287 /* SourceControlGeneralView.swift in Sources */, 587B9E8929301D8F00AC7927 /* GitHubGist.swift in Sources */, - 0485EB1F27E7458B00138301 /* WorkspaceCodeFileView.swift in Sources */, + 0485EB1F27E7458B00138301 /* EditorAreaFileView.swift in Sources */, 6C092EDA2A53A58600489202 /* EditorLayout+StateRestoration.swift in Sources */, 6C092EE02A53BFCF00489202 /* WorkspaceStateKey.swift in Sources */, 613899B52B6E700300A5CAF6 /* FuzzySearchModels.swift in Sources */, 58D01C94293167DC00C5B6B4 /* Color+HEX.swift in Sources */, 6C578D8729CD345900DC73B2 /* ExtensionSceneView.swift in Sources */, B640A9A129E2188F00715F20 /* View+NavigationBarBackButtonVisible.swift in Sources */, - 58798251292E78D80085B254 /* OtherFileView.swift in Sources */, 587B9E7929301D8F00AC7927 /* GitHubIssueRouter.swift in Sources */, 587B9E8029301D8F00AC7927 /* GitHubConfiguration.swift in Sources */, 58822524292C280D00E83CDE /* StatusBarView.swift in Sources */, @@ -3626,6 +3593,7 @@ B65B10F22B07D34F002852CF /* GitRemote.swift in Sources */, B6A43C5D29FC4AF00027E0E0 /* CreateSSHKeyView.swift in Sources */, B6EA200229DB7F81001BF195 /* View+ConstrainHeightToWindow.swift in Sources */, + 66F370342BEE537B00D3B823 /* NonTextFileView.swift in Sources */, B68C7C212A01DEFE004EA6D6 /* GitHubComment.swift in Sources */, 613899B72B6E702F00A5CAF6 /* String+LengthOfMatchingPrefix.swift in Sources */, 6C48D8F42972DB1A00D6D205 /* Env+Window.swift in Sources */, diff --git a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index cb92aa4d4..7790485df 100644 --- a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "029e3feb7277e502c419e04acfc23af6dd70755f3984e9902ec582890724706b", + "originHash" : "41fcbec1ecbb7853d9ead798bba9d46f35f28767f4d41a009c8eeee022e99a84", "pins" : [ { "identity" : "anycodable", @@ -87,7 +87,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/Wouter01/LogStream", "state" : { - "revision" : "5378bafdbf5de66b69da8cca9df9d16e19bfcf89", + "revision" : "6f83694b2675dcf3b1cea0a52546ff4469c18282", "version" : "1.3.0" } }, @@ -200,5 +200,5 @@ } } ], - "version" : 2 + "version" : 3 } diff --git a/CodeEdit/Features/CodeEditUI/Views/EffectView.swift b/CodeEdit/Features/CodeEditUI/Views/EffectView.swift index 0c60b1384..16389ee2c 100644 --- a/CodeEdit/Features/CodeEditUI/Views/EffectView.swift +++ b/CodeEdit/Features/CodeEditUI/Views/EffectView.swift @@ -26,7 +26,7 @@ struct EffectView: NSViewRepresentable { /// /// By setting the /// [`emphasized`](https://developer.apple.com/documentation/appkit/nsvisualeffectview/1644721-isemphasized) - /// flag the emphasized state of the material will be used if available. + /// flag, the emphasized state of the material will be used if available. /// /// - Parameters: /// - material: The material to use. Defaults to `.headerView`. diff --git a/CodeEdit/Features/CodeFile/Image/ImageFileView.swift b/CodeEdit/Features/CodeFile/Image/ImageFileView.swift deleted file mode 100644 index 8e599ecf5..000000000 --- a/CodeEdit/Features/CodeFile/Image/ImageFileView.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// ImageFileView.swift -// CodeEditModules/CodeFile -// -// Created by Nanashi Li on 2022/04/16. -// - -import SwiftUI - -struct ImageFileView: View { - - private let image: NSImage? - - init(image: NSImage?) { - self.image = image - } - - var body: some View { - GeometryReader { proxy in - if let image { - if image.size.width > proxy.size.width || image.size.height > proxy.size.height { - Image(nsImage: image) - .resizable() - .scaledToFit() - } else { - Image(nsImage: image) - .frame(width: proxy.size.width, height: proxy.size.height) - } - } else { - EmptyView() - } - } - } -} diff --git a/CodeEdit/Features/CodeFile/Other/OtherFileView.swift b/CodeEdit/Features/CodeFile/Other/OtherFileView.swift deleted file mode 100644 index f501dae72..000000000 --- a/CodeEdit/Features/CodeFile/Other/OtherFileView.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// OtherFileView.swift -// -// -// Created by Shibo Tong on 10/7/2022. -// - -import SwiftUI -import QuickLookUI - -/// A SwiftUI Wrapper for `QLPreviewView` -/// Mainly used for other unsupported files -/// ## Usage -/// ```swift -/// OtherFileView(otherFile) -/// ``` -struct OtherFileView: NSViewRepresentable { - - private var otherFile: CodeFileDocument - - /// Initialize the OtherFileView - /// - Parameter otherFile: a file which contains URL to show preview - init( - _ otherFile: CodeFileDocument - ) { - self.otherFile = otherFile - } - - func makeNSView(context: Context) -> QLPreviewView { - let qlPreviewView = QLPreviewView() - if let previewItemURL = otherFile.previewItemURL { - qlPreviewView.previewItem = previewItemURL as QLPreviewItem - } - return qlPreviewView - } - - /// Update preview file when file changed - func updateNSView(_ nsView: QLPreviewView, context: Context) { - guard let currentPreviewItem = nsView.previewItem else { - return - } - if let previewItemURL = otherFile.previewItemURL, previewItemURL != currentPreviewItem.previewItemURL { - nsView.previewItem = previewItemURL as QLPreviewItem - } - } -} diff --git a/CodeEdit/Features/CodeFile/CodeFileDocument.swift b/CodeEdit/Features/Documents/CodeFileDocument.swift similarity index 82% rename from CodeEdit/Features/CodeFile/CodeFileDocument.swift rename to CodeEdit/Features/Documents/CodeFileDocument.swift index 9cdde5b23..b92d529c6 100644 --- a/CodeEdit/Features/CodeFile/CodeFileDocument.swift +++ b/CodeEdit/Features/Documents/CodeFileDocument.swift @@ -1,5 +1,5 @@ // -// CodeFile.swift +// CodeFileDocument.swift // CodeEditModules/CodeFile // // Created by Rehatbir Singh on 12/03/2022. @@ -9,7 +9,6 @@ import AppKit import Foundation import SwiftUI import UniformTypeIdentifiers -import QuickLookUI import CodeEditSourceEditor import CodeEditTextView import CodeEditLanguages @@ -22,7 +21,7 @@ enum CodeFileError: Error { } @objc(CodeFileDocument) -final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem { +final class CodeFileDocument: NSDocument, ObservableObject { struct OpenOptions { let cursorPositions: [CursorPosition] } @@ -41,37 +40,33 @@ final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem { /// Document-specific overridden line wrap preference. @Published var wrapLines: Bool? - /* - This is the main type of the document. - For example, if the file is end with '.png', it will be an image, - if the file is end with '.py', it will be a text file. - If text content is not empty, return text - If its neither image or text, this could be nil. - */ - var typeOfFile: UTType? { + /// The type of data this document contains. + /// + /// If for example, the file ends with `.py`, its type is a text file. + /// Or if it ends with `.png`, then it is an image. + /// Same goes for PDF and video formats. + /// + /// Also, if the text content is not empty, it is a text file. + /// + /// - Note: The UTType doesn't necessarily mean the file extension, it can be the MIME + /// type or any other form of data representation. + var utType: UTType? { if !self.content.isEmpty { - return UTType.text + return .text } guard let fileType, let type = UTType(fileType) else { return nil } - if type.conforms(to: UTType.image) { - return UTType.image + if type.conforms(to: .text) { + return .text } - if type.conforms(to: UTType.text) { - return UTType.text + if type.conforms(to: .image) { + return .image } - if type.conforms(to: .data) { - return .data + if type.conforms(to: .pdf) { + return .pdf } - return nil - } - - /* - This is the QLPreviewItemURL - */ - var previewItemURL: URL? { - fileURL + return type } /// Specify options for opening the file such as the initial cursor positions. diff --git a/CodeEdit/Features/Documents/Views/WorkspaceCodeFileView.swift b/CodeEdit/Features/Documents/Views/WorkspaceCodeFileView.swift deleted file mode 100644 index b18c4a65f..000000000 --- a/CodeEdit/Features/Documents/Views/WorkspaceCodeFileView.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// WorkspaceCodeFileView.swift -// CodeEdit -// -// Created by Pavel Kasila on 20.03.22. -// - -import SwiftUI -import UniformTypeIdentifiers -import CodeEditSourceEditor - -struct WorkspaceCodeFileView: View { - - @EnvironmentObject private var editorManager: EditorManager - - @EnvironmentObject private var editor: Editor - - var file: CEWorkspaceFile - var textViewCoordinators: [TextViewCoordinator] = [] - - @State private var update: Bool = false - - @ViewBuilder var codeView: some View { - if let document = file.fileDocument { - Group { - switch document.typeOfFile { - case .some(.text), .some(.data): - CodeFileView(codeFile: document, textViewCoordinators: textViewCoordinators) - default: - otherFileView(document, for: file) - } - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - } else { - if update { - Spacer() - } - Spacer() - VStack(spacing: 10) { - ProgressView() - Text("Opening \(file.name)...") - } - Spacer() - .onAppear { - Task.detached { - let contentType = try await file.url.resourceValues(forKeys: [.contentTypeKey]).contentType - let codeFile = try await CodeFileDocument( - for: file.url, - withContentsOf: file.url, - ofType: contentType?.identifier ?? "" - ) - await MainActor.run { - file.fileDocument = codeFile - CodeEditDocumentController.shared.addDocument(codeFile) - update.toggle() - } - } - } - } - } - - @ViewBuilder - private func otherFileView( - _ otherFile: CodeFileDocument, - for item: CEWorkspaceFile - ) -> some View { - VStack(spacing: 0) { - if let url = otherFile.previewItemURL, - let image = NSImage(contentsOf: url), - otherFile.typeOfFile == .image { - GeometryReader { proxy in - if image.size.width > proxy.size.width || image.size.height > proxy.size.height { - OtherFileView(otherFile) - } else { - OtherFileView(otherFile) - .frame( - width: proxy.size.width * (proxy.size.width / image.size.width), - height: proxy.size.height - ) - .position(x: proxy.frame(in: .local).midX, y: proxy.frame(in: .local).midY) - } - } - } else { - OtherFileView(otherFile) - } - } - } - - var body: some View { - codeView - .frame(maxWidth: .infinity, maxHeight: .infinity) - .onHover { hover in - DispatchQueue.main.async { - if hover { - NSCursor.iBeam.push() - } else { - NSCursor.pop() - } - } - } - } -} diff --git a/CodeEdit/Features/Editor/Views/AnyFileView.swift b/CodeEdit/Features/Editor/Views/AnyFileView.swift new file mode 100644 index 000000000..9851fa6af --- /dev/null +++ b/CodeEdit/Features/Editor/Views/AnyFileView.swift @@ -0,0 +1,36 @@ +// +// AnyFileView.swift +// CodeEdit +// +// Created by Paul Ebose on 2024/5/9. +// + +import SwiftUI +import QuickLookUI + +/// A view for previewing any kind of file. +/// +/// ```swift +/// AnyFileView(fileURL) +/// ``` +/// If the file cannot be previewed, a file icon thumbnail is shown instead. +struct AnyFileView: NSViewRepresentable { + + /// URL of the file to preview. You can pass in any file type. + private let fileURL: URL + + init(_ fileURL: URL) { + self.fileURL = fileURL + } + + func makeNSView(context: Context) -> QLPreviewView { + let qlPreviewView = QLPreviewView() + qlPreviewView.previewItem = fileURL as any QLPreviewItem + return qlPreviewView + } + + func updateNSView(_ qlPreviewView: QLPreviewView, context: Context) { + qlPreviewView.previewItem = fileURL as any QLPreviewItem + } + +} diff --git a/CodeEdit/Features/CodeFile/CodeFileView.swift b/CodeEdit/Features/Editor/Views/CodeFileView.swift similarity index 100% rename from CodeEdit/Features/CodeFile/CodeFileView.swift rename to CodeEdit/Features/Editor/Views/CodeFileView.swift diff --git a/CodeEdit/Features/Editor/Views/EditorAreaFileView.swift b/CodeEdit/Features/Editor/Views/EditorAreaFileView.swift new file mode 100644 index 000000000..4746c6b82 --- /dev/null +++ b/CodeEdit/Features/Editor/Views/EditorAreaFileView.swift @@ -0,0 +1,76 @@ +// +// EditorAreaFileView.swift +// CodeEdit +// +// Created by Pavel Kasila on 20.03.22. +// + +import AppKit +import AVKit +import CodeEditSourceEditor +import SwiftUI + +struct EditorAreaFileView: View { + + @EnvironmentObject private var editorManager: EditorManager + + @EnvironmentObject private var editor: Editor + + @Environment(\.edgeInsets) + private var edgeInsets + + var file: CEWorkspaceFile + var textViewCoordinators: [TextViewCoordinator] = [] + + @State private var update: Bool = false + + @ViewBuilder var editorAreaFileView: some View { + if let document = file.fileDocument { + + if let utType = document.utType, utType.conforms(to: .text) { + CodeFileView(codeFile: document, textViewCoordinators: textViewCoordinators) + } else { + NonTextFileView(fileDocument: document) + .padding(.top, edgeInsets.top - 1.74) // Use the magic number to fine-tune its appearance. + .padding(.bottom, StatusBarView.height + 1.26) // Use the magic number to fine-tune its appearance. + } + + } else { + if update { + Spacer() + } + Spacer() + LoadingFileView(file.name) + Spacer() + .onAppear { + Task.detached { + let contentType = try await file.url.resourceValues(forKeys: [.contentTypeKey]).contentType + let codeFile = try await CodeFileDocument( + for: file.url, + withContentsOf: file.url, + ofType: contentType?.identifier ?? "" + ) + await MainActor.run { + file.fileDocument = codeFile + CodeEditDocumentController.shared.addDocument(codeFile) + update.toggle() + } + } + } + } + } + + var body: some View { + editorAreaFileView + .frame(maxWidth: .infinity, maxHeight: .infinity) + .onHover { hover in + DispatchQueue.main.async { + if hover { + NSCursor.iBeam.push() + } else { + NSCursor.pop() + } + } + } + } +} diff --git a/CodeEdit/Features/Editor/Views/EditorView.swift b/CodeEdit/Features/Editor/Views/EditorAreaView.swift similarity index 97% rename from CodeEdit/Features/Editor/Views/EditorView.swift rename to CodeEdit/Features/Editor/Views/EditorAreaView.swift index 6ca74ae35..11a63f8d0 100644 --- a/CodeEdit/Features/Editor/Views/EditorView.swift +++ b/CodeEdit/Features/Editor/Views/EditorAreaView.swift @@ -1,5 +1,5 @@ // -// EditorView.swift +// EditorAreaView.swift // CodeEdit // // Created by Wouter Hennen on 16/02/2023. @@ -7,7 +7,7 @@ import SwiftUI -struct EditorView: View { +struct EditorAreaView: View { @AppSettings(\.general.showEditorPathBar) var showEditorPathBar @@ -40,7 +40,7 @@ struct EditorView: View { VStack { if let selected = editor.selectedTab { - WorkspaceCodeFileView( + EditorAreaFileView( file: selected.file, textViewCoordinators: [selected.rangeTranslator].compactMap({ $0 }) ) diff --git a/CodeEdit/Features/Editor/Views/EditorLayoutView.swift b/CodeEdit/Features/Editor/Views/EditorLayoutView.swift index 408bf476a..0402aae00 100644 --- a/CodeEdit/Features/Editor/Views/EditorLayoutView.swift +++ b/CodeEdit/Features/Editor/Views/EditorLayoutView.swift @@ -26,7 +26,7 @@ struct EditorLayoutView: View { VStack { switch layout { case .one(let detailEditor): - EditorView(editor: detailEditor, focus: $focus) + EditorAreaView(editor: detailEditor, focus: $focus) .transformEnvironment(\.edgeInsets) { insets in switch isAtEdge { case .all: diff --git a/CodeEdit/Features/Editor/Views/ImageFileView.swift b/CodeEdit/Features/Editor/Views/ImageFileView.swift new file mode 100644 index 000000000..044f4ed8d --- /dev/null +++ b/CodeEdit/Features/Editor/Views/ImageFileView.swift @@ -0,0 +1,52 @@ +// +// ImageFileView.swift +// CodeEdit +// +// Created by Paul Ebose on 2024/5/9. +// + +import SwiftUI + +/// A view for previewing an image, while respecting its dimensions. +/// +/// It receives a URL to an image file and attempts to preview it. +/// +/// ```swift +/// ImageFileView(imageURL) +/// ``` +/// This implementation allows for proper image scaling, especially when the image dimensions are smaller than +/// the size of the image view area. +/// +/// If the preview image cannot be created, it shows a *"Cannot preview image"* text. +struct ImageFileView: View { + + /// URL of the image you want to preview. + private let imageURL: URL + + init(_ imageURL: URL) { + self.imageURL = imageURL + } + + var body: some View { + if let nsImage = NSImage(contentsOf: imageURL), + let imageReps = nsImage.representations.first { + + let pixelWidth = CGFloat(imageReps.pixelsWide) + let pixelHeight = CGFloat(imageReps.pixelsHigh) + + GeometryReader { proxy in + ZStack { + AnyFileView(imageURL) + .frame( + maxWidth: min(pixelWidth, proxy.size.width, nsImage.size.width), + maxHeight: min(pixelHeight, proxy.size.height, nsImage.size.height) + ) + } + .frame(width: proxy.size.width, height: proxy.size.height) + } + } else { + Text("Cannot preview image") + } + } + +} diff --git a/CodeEdit/Features/Editor/Views/LoadingFileView.swift b/CodeEdit/Features/Editor/Views/LoadingFileView.swift new file mode 100644 index 000000000..71eb34699 --- /dev/null +++ b/CodeEdit/Features/Editor/Views/LoadingFileView.swift @@ -0,0 +1,32 @@ +// +// LoadingFileView.swift +// CodeEdit +// +// Created by Paul Ebose on 2024/5/9. +// + +import SwiftUI + +/// A placeholder view that shows a spinner and text. +/// +/// It optionally receives a file name. +/// ```swift +/// LoadingFileView(filename) +/// LoadingFileView() +/// ``` +struct LoadingFileView: View { + + /// Name of file that is about to open. + private var filename = "" + + init(_ filename: String = "") { + self.filename = filename + } + + var body: some View { + VStack(spacing: 10) { + ProgressView() + Text("Opening \(filename)...") + } + } +} diff --git a/CodeEdit/Features/Editor/Views/NonTextFileView.swift b/CodeEdit/Features/Editor/Views/NonTextFileView.swift new file mode 100644 index 000000000..cb5c776bc --- /dev/null +++ b/CodeEdit/Features/Editor/Views/NonTextFileView.swift @@ -0,0 +1,42 @@ +// +// NonTextFileView.swift +// CodeEdit +// +// Created by Paul Ebose on 2024/5/10. +// + +import SwiftUI + +/// Determines what type of file is passed in, and previews it accordingly. +/// +/// ```swift +/// NonTextFileView(fileDocument) +/// ``` +struct NonTextFileView: View { + + /// The file document you wish to open. + let fileDocument: CodeFileDocument + + var body: some View { + + if let fileURL = fileDocument.fileURL { + + switch fileDocument.utType { + case .some(.image): + ImageFileView(fileURL) + + case .some(.pdf): + PDFFileView(fileURL) + + default: + AnyFileView(fileURL) + } + + } else { + ZStack { + Text("Cannot retrieve URL to the file you opened.") + } + } + + } +} diff --git a/CodeEdit/Features/Editor/Views/PDFFileView.swift b/CodeEdit/Features/Editor/Views/PDFFileView.swift new file mode 100644 index 000000000..60058807a --- /dev/null +++ b/CodeEdit/Features/Editor/Views/PDFFileView.swift @@ -0,0 +1,59 @@ +// +// PDFFileView.swift +// CodeEdit +// +// Created by Paul Ebose on 2024/5/7. +// + +import SwiftUI +import PDFKit.PDFView + +/// A view for previewing a PDF file. +/// +/// It takes in a file URL and attempts to preview a PDF. +/// +/// ```swift +/// PDFFileView(fileURL) +/// ``` +/// +/// This view provides a context menu that is the same as the one in the native MacOS Preview +/// application, for PDF files. +/// +/// This view also allows for proper scaling of the PDF. +/// +/// - Note: If the file located at the `fileURL` cannot be previewed as a PDF, nothing happens, no redraw or anything. +struct PDFFileView: NSViewRepresentable { + + /// URL of the PDF file you want to preview. + private let fileURL: URL + + init(_ fileURL: URL) { + self.fileURL = fileURL + } + + func makeNSView(context: Context) -> PDFView { + let pdfView = attachPDFDocumentToView(PDFView()) + return pdfView + } + + func updateNSView(_ pdfView: PDFView, context: Context) { + attachPDFDocumentToView(pdfView) + } + + /// Creates a PDF document using ``PDFFileView`` `.fileUrl`, and attaches it to the passed in `pdfView`. + /// - Parameters: + /// - pdfView: The [`PDFView`](https://developer.apple.com/documentation/pdfkit/pdfview) you wish to modify. + /// - Returns: A modified `pdfView` if a valid PDF was created, or an unmodified `pdfView` if it could not create a + /// valid PDF. + @discardableResult + private func attachPDFDocumentToView (_ pdfView: PDFView) -> PDFView { + guard let pdfDocument = PDFDocument(url: fileURL) else { + // What can happen is the view doesn't redraw, so whatever was in the editor area view remains as is. + return pdfView + } + pdfView.document = pdfDocument + pdfView.backgroundColor = NSColor.controlBackgroundColor + return pdfView + } + +} diff --git a/CodeEdit/Features/CodeFile/WindowCodeFileView.swift b/CodeEdit/Features/Editor/Views/WindowCodeFileView.swift similarity index 100% rename from CodeEdit/Features/CodeFile/WindowCodeFileView.swift rename to CodeEdit/Features/Editor/Views/WindowCodeFileView.swift diff --git a/CodeEdit/Features/QuickOpen/Views/NSTableViewWrapper.swift b/CodeEdit/Features/QuickOpen/Views/NSTableViewWrapper.swift index c538f8e0f..c2b3383e1 100644 --- a/CodeEdit/Features/QuickOpen/Views/NSTableViewWrapper.swift +++ b/CodeEdit/Features/QuickOpen/Views/NSTableViewWrapper.swift @@ -1,5 +1,5 @@ // -// NotList.swift +// NSTableViewWrapper.swift // CodeEdit // // Created by Wouter Hennen on 18/03/2023. diff --git a/CodeEdit/Features/QuickOpen/Views/QuickOpenPreviewView.swift b/CodeEdit/Features/QuickOpen/Views/QuickOpenPreviewView.swift index 38ba4953d..caaf72806 100644 --- a/CodeEdit/Features/QuickOpen/Views/QuickOpenPreviewView.swift +++ b/CodeEdit/Features/QuickOpen/Views/QuickOpenPreviewView.swift @@ -14,9 +14,7 @@ struct QuickOpenPreviewView: View { @ObservedObject var document: CodeFileDocument - init( - item: CEWorkspaceFile - ) { + init(item: CEWorkspaceFile) { self.item = item let doc = try? CodeFileDocument( for: item.url, @@ -27,32 +25,10 @@ struct QuickOpenPreviewView: View { } var body: some View { - if let url = document.fileURL { - if url.isImage() { - if let image = NSImage(contentsOf: url) { - GeometryReader { proxy in - if image.size.width > proxy.size.width || image.size.height > proxy.size.height { - OtherFileView(document) - } else { - // FIXME: The following code causes a bug where the image size doesn't change when zooming. - // The proper version found in WorkspaceCodeFile.swift line 59 to 60. - // Cannot use that code as the image obscures the open quickly overlay. - // There might be a solution for this in QuickOpenView.swift or OverlayView.swift - - OtherFileView(document) - .frame( - width: image.size.width, - height: image.size.height - ) - .position(x: proxy.frame(in: .local).midX, y: proxy.frame(in: .local).midY) - } - } - } else { - OtherFileView(document) - } - } else { - CodeFileView(codeFile: document, isEditable: false) - } + if let utType = document.utType, utType.conforms(to: .text) { + CodeFileView(codeFile: document, isEditable: false) + } else { + NonTextFileView(fileDocument: document) } } } diff --git a/CodeEdit/Utils/Extensions/URL/URL+isImage.swift b/CodeEdit/Utils/Extensions/URL/URL+isImage.swift deleted file mode 100644 index 6e3dea337..000000000 --- a/CodeEdit/Utils/Extensions/URL/URL+isImage.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// URL+isImage.swift -// CodeEdit -// -// Created by Raymond Vleeshouwer on 14/05/23. -// - -import Foundation - -extension URL { - func isImage() -> Bool { - let ext: String = self.pathExtension.lowercased() - - // A list of supported file types by QLPreviewItem - // Some of the image file types (in UTType) are not supported by QLPreviewItem - let quickLookImageFileTypes: [String] = [ - "png", - "jpg", - "jpeg", - "bmp", - "pdf", - "heic", - "webp", - "tiff", - "gif", - "tga", - "avif", - "psd", - "svg" - ] - - if quickLookImageFileTypes.contains(ext) { - return true - } else { - return false - } - } -} diff --git a/Documentation.docc/App Window/App Window.md b/Documentation.docc/App Window/App Window.md index 999608998..a1bd2b9c8 100644 --- a/Documentation.docc/App Window/App Window.md +++ b/Documentation.docc/App Window/App Window.md @@ -11,9 +11,14 @@ A collection of all the views that make up the main app window. ### Main Content +- ``EditorAreaView`` +- ``EditorAreaFileView`` - ``CodeFileView`` +- ``NonTextFileView`` +- ``AnyFileView`` +- ``LoadingFileView`` - ``ImageFileView`` -- ``OtherFileView`` +- ``PDFFileView`` ### PathBar diff --git a/Documentation.docc/Documentation.md b/Documentation.docc/Documentation.md index 95dd8eba5..5825064d5 100644 --- a/Documentation.docc/Documentation.md +++ b/Documentation.docc/Documentation.md @@ -41,8 +41,6 @@ - ``CEWorkspaceFileManager`` - ``CodeFileDocument`` - ``CodeEditDocumentController`` -- ``WorkspaceCodeFileView`` -- ``WorkspaceNotificationModel`` ### Feedback