Adding introspection for TabView

This commit is contained in:
Selim Mustafaev 2025-04-30 17:53:46 +03:00
parent bbaef15acb
commit 2b31f11412
4 changed files with 70 additions and 14 deletions

View File

@ -100,6 +100,8 @@
7A91CE952DC2422B00DBA953 /* HideTabBarModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91CE942DC2422B00DBA953 /* HideTabBarModifier.swift */; }; 7A91CE952DC2422B00DBA953 /* HideTabBarModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91CE942DC2422B00DBA953 /* HideTabBarModifier.swift */; };
7A91CE982DC243AD00DBA953 /* TitleModeInlineModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91CE972DC243AD00DBA953 /* TitleModeInlineModifier.swift */; }; 7A91CE982DC243AD00DBA953 /* TitleModeInlineModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91CE972DC243AD00DBA953 /* TitleModeInlineModifier.swift */; };
7A91CE9A2DC2470F00DBA953 /* TextFieldDumbModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91CE992DC2470F00DBA953 /* TextFieldDumbModifier.swift */; }; 7A91CE9A2DC2470F00DBA953 /* TextFieldDumbModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91CE992DC2470F00DBA953 /* TextFieldDumbModifier.swift */; };
7A91CE9D2DC26B8E00DBA953 /* SwiftUIIntrospect in Frameworks */ = {isa = PBXBuildFile; productRef = 7A91CE9C2DC26B8E00DBA953 /* SwiftUIIntrospect */; };
7A91CE9F2DC26BC300DBA953 /* TabBarControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91CE9E2DC26BC300DBA953 /* TabBarControllerDelegate.swift */; };
7A9519792D80B3E800E69883 /* AudioRecordService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9519782D80B3E800E69883 /* AudioRecordService.swift */; }; 7A9519792D80B3E800E69883 /* AudioRecordService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9519782D80B3E800E69883 /* AudioRecordService.swift */; };
7A95197B2D80B41600E69883 /* AudioRecordServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A95197A2D80B41600E69883 /* AudioRecordServiceProtocol.swift */; }; 7A95197B2D80B41600E69883 /* AudioRecordServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A95197A2D80B41600E69883 /* AudioRecordServiceProtocol.swift */; };
7A95197D2D80B43D00E69883 /* AudioRecordError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A95197C2D80B43D00E69883 /* AudioRecordError.swift */; }; 7A95197D2D80B43D00E69883 /* AudioRecordError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A95197C2D80B43D00E69883 /* AudioRecordError.swift */; };
@ -345,6 +347,7 @@
7A91CE942DC2422B00DBA953 /* HideTabBarModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideTabBarModifier.swift; sourceTree = "<group>"; }; 7A91CE942DC2422B00DBA953 /* HideTabBarModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideTabBarModifier.swift; sourceTree = "<group>"; };
7A91CE972DC243AD00DBA953 /* TitleModeInlineModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleModeInlineModifier.swift; sourceTree = "<group>"; }; 7A91CE972DC243AD00DBA953 /* TitleModeInlineModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleModeInlineModifier.swift; sourceTree = "<group>"; };
7A91CE992DC2470F00DBA953 /* TextFieldDumbModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldDumbModifier.swift; sourceTree = "<group>"; }; 7A91CE992DC2470F00DBA953 /* TextFieldDumbModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldDumbModifier.swift; sourceTree = "<group>"; };
7A91CE9E2DC26BC300DBA953 /* TabBarControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarControllerDelegate.swift; sourceTree = "<group>"; };
7A92D0AB240425B100EF3B77 /* ATGMediaBrowser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ATGMediaBrowser.framework; path = Carthage/Build/iOS/ATGMediaBrowser.framework; sourceTree = "<group>"; }; 7A92D0AB240425B100EF3B77 /* ATGMediaBrowser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ATGMediaBrowser.framework; path = Carthage/Build/iOS/ATGMediaBrowser.framework; sourceTree = "<group>"; };
7A9519782D80B3E800E69883 /* AudioRecordService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecordService.swift; sourceTree = "<group>"; }; 7A9519782D80B3E800E69883 /* AudioRecordService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecordService.swift; sourceTree = "<group>"; };
7A95197A2D80B41600E69883 /* AudioRecordServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecordServiceProtocol.swift; sourceTree = "<group>"; }; 7A95197A2D80B41600E69883 /* AudioRecordServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecordServiceProtocol.swift; sourceTree = "<group>"; };
@ -444,6 +447,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
7A91CE9D2DC26B8E00DBA953 /* SwiftUIIntrospect in Frameworks */,
7A386A4B2DAC35F10051676A /* ClusterMap in Frameworks */, 7A386A4B2DAC35F10051676A /* ClusterMap in Frameworks */,
7A7AA2CA2DA2C85100276D83 /* RealmSwift in Frameworks */, 7A7AA2CA2DA2C85100276D83 /* RealmSwift in Frameworks */,
7A386A4D2DAC35F10051676A /* ClusterMapSwiftUI in Frameworks */, 7A386A4D2DAC35F10051676A /* ClusterMapSwiftUI in Frameworks */,
@ -976,6 +980,7 @@
7AC44B812DB390B900ADC026 /* MainTabScreen.swift */, 7AC44B812DB390B900ADC026 /* MainTabScreen.swift */,
7AE8CBB62DBA3E4E005EF1AB /* MainSplitScreen.swift */, 7AE8CBB62DBA3E4E005EF1AB /* MainSplitScreen.swift */,
7AFFF79F2DBAAFF300EE2DEE /* SideBarItem.swift */, 7AFFF79F2DBAAFF300EE2DEE /* SideBarItem.swift */,
7A91CE9E2DC26BC300DBA953 /* TabBarControllerDelegate.swift */,
); );
path = MainScreen; path = MainScreen;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1118,6 +1123,7 @@
7A7AA2C92DA2C85100276D83 /* RealmSwift */, 7A7AA2C92DA2C85100276D83 /* RealmSwift */,
7A386A4A2DAC35F10051676A /* ClusterMap */, 7A386A4A2DAC35F10051676A /* ClusterMap */,
7A386A4C2DAC35F10051676A /* ClusterMapSwiftUI */, 7A386A4C2DAC35F10051676A /* ClusterMapSwiftUI */,
7A91CE9C2DC26B8E00DBA953 /* SwiftUIIntrospect */,
); );
productName = AutoCat; productName = AutoCat;
productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */; productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */;
@ -1238,6 +1244,7 @@
7A6C4D9C2C56BCA600982597 /* XCRemoteSwiftPackageReference "SwiftLocation" */, 7A6C4D9C2C56BCA600982597 /* XCRemoteSwiftPackageReference "SwiftLocation" */,
7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */, 7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */,
7A386A492DAC35F10051676A /* XCRemoteSwiftPackageReference "ClusterMap" */, 7A386A492DAC35F10051676A /* XCRemoteSwiftPackageReference "ClusterMap" */,
7A91CE9B2DC26B8E00DBA953 /* XCRemoteSwiftPackageReference "swiftui-introspect" */,
); );
productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */; productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -1361,6 +1368,7 @@
7A4955822D58CCF900912E66 /* HistoryFilter.swift in Sources */, 7A4955822D58CCF900912E66 /* HistoryFilter.swift in Sources */,
7A4322912CB2CC8A00085CF6 /* FiltersScreen.swift in Sources */, 7A4322912CB2CC8A00085CF6 /* FiltersScreen.swift in Sources */,
7ABD1B472D044A3200B43213 /* GalleryScreen.swift in Sources */, 7ABD1B472D044A3200B43213 /* GalleryScreen.swift in Sources */,
7A91CE9F2DC26BC300DBA953 /* TabBarControllerDelegate.swift in Sources */,
7A71580C2C44453200852088 /* AdsScreen.swift in Sources */, 7A71580C2C44453200852088 /* AdsScreen.swift in Sources */,
7AE8CBB52DBA3B55005EF1AB /* Router.swift in Sources */, 7AE8CBB52DBA3B55005EF1AB /* Router.swift in Sources */,
7AADD4452DB2D4D60027FD7B /* MapInput.swift in Sources */, 7AADD4452DB2D4D60027FD7B /* MapInput.swift in Sources */,
@ -1649,7 +1657,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements; CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 159; CURRENT_PROJECT_VERSION = 160;
DEVELOPMENT_TEAM = 46DTTB8X4S; DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist; INFOPLIST_FILE = AutoCat/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AutoCat; INFOPLIST_KEY_CFBundleDisplayName = AutoCat;
@ -1678,7 +1686,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements; CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 159; CURRENT_PROJECT_VERSION = 160;
DEVELOPMENT_TEAM = 46DTTB8X4S; DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist; INFOPLIST_FILE = AutoCat/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AutoCat; INFOPLIST_KEY_CFBundleDisplayName = AutoCat;
@ -1961,6 +1969,14 @@
minimumVersion = 6.0.0; minimumVersion = 6.0.0;
}; };
}; };
7A91CE9B2DC26B8E00DBA953 /* XCRemoteSwiftPackageReference "swiftui-introspect" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/siteline/swiftui-introspect";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.3.0;
};
};
7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */ = { 7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/Kolos65/Mockable"; repositoryURL = "https://github.com/Kolos65/Mockable";
@ -1997,6 +2013,11 @@
package = 7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */; package = 7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */;
productName = RealmSwift; productName = RealmSwift;
}; };
7A91CE9C2DC26B8E00DBA953 /* SwiftUIIntrospect */ = {
isa = XCSwiftPackageProductDependency;
package = 7A91CE9B2DC26B8E00DBA953 /* XCRemoteSwiftPackageReference "swiftui-introspect" */;
productName = SwiftUIIntrospect;
};
7AABB1F1267E9CC800D7AB32 /* SwiftDate */ = { 7AABB1F1267E9CC800D7AB32 /* SwiftDate */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = 7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */; package = 7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */;

View File

@ -1,5 +1,5 @@
{ {
"originHash" : "b26032c73d0741690e860809b31156025c85a200a7d53a64391683433e6a82a4", "originHash" : "9f3158dea626a001d81e00d3727621c7c4361dcfcca02075d1f7b1029ae36416",
"pins" : [ "pins" : [
{ {
"identity" : "clustermap", "identity" : "clustermap",
@ -64,6 +64,15 @@
"version" : "6.0.0" "version" : "6.0.0"
} }
}, },
{
"identity" : "swiftui-introspect",
"kind" : "remoteSourceControl",
"location" : "https://github.com/siteline/swiftui-introspect",
"state" : {
"revision" : "807f73ce09a9b9723f12385e592b4e0aaebd3336",
"version" : "1.3.0"
}
},
{ {
"identity" : "xctest-dynamic-overlay", "identity" : "xctest-dynamic-overlay",
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",

View File

@ -8,11 +8,11 @@
import SwiftUI import SwiftUI
import AutoCatCore import AutoCatCore
import SwiftUIIntrospect
struct MainTabScreen: View { struct MainTabScreen: View {
@State private var selection: SideBarItem? = .history @State private var selection: SideBarItem? = .history
@State private var oldSelection: SideBarItem? = .history
@State var historyViewModel: HistoryViewModel @State var historyViewModel: HistoryViewModel
@State var recordsViewModel: RecordsViewModel @State var recordsViewModel: RecordsViewModel
@ -64,26 +64,18 @@ struct MainTabScreen: View {
Label("History", systemImage: "clock.arrow.circlepath") Label("History", systemImage: "clock.arrow.circlepath")
} }
.tag(SideBarItem.history) .tag(SideBarItem.history)
.onAppear { oldSelection = selection }
RecordsScreen(selectedTab: $selection, viewModel: recordsViewModel) RecordsScreen(selectedTab: $selection, viewModel: recordsViewModel)
.tabItem { .tabItem {
Label("Records", systemImage: "waveform") Label("Records", systemImage: "waveform")
} }
.tag(SideBarItem.records) .tag(SideBarItem.records)
.onAppear { oldSelection = selection }
Text("") Text("")
.tabItem { .tabItem {
Label("", systemImage: "plus") Label("", systemImage: "plus")
} }
.tag(SideBarItem.plus) .tag(SideBarItem.plus)
.onAppear {
DispatchQueue.main.async {
checkNumberSheetOpened = true
selection = oldSelection
}
}
NavigationStack { NavigationStack {
SearchScreen(viewModel: searchViewModel) SearchScreen(viewModel: searchViewModel)
@ -92,14 +84,18 @@ struct MainTabScreen: View {
Label("Search", systemImage: "magnifyingglass") Label("Search", systemImage: "magnifyingglass")
} }
.tag(SideBarItem.search) .tag(SideBarItem.search)
.onAppear { oldSelection = selection }
SettingsScreen() SettingsScreen()
.tabItem { .tabItem {
Label("Settings", systemImage: "gear") Label("Settings", systemImage: "gear")
} }
.tag(SideBarItem.settings) .tag(SideBarItem.settings)
.onAppear { oldSelection = selection } }
.introspect(.tabView, on: .iOS(.v17, .v18)) { controller in
controller.delegate = TabBarControllerDelegate.shared
TabBarControllerDelegate.shared.action = {
checkNumberSheetOpened = true
}
} }
} }

View File

@ -0,0 +1,30 @@
//
// TabBarControllerDelegate.swift
// AutoCat
//
// Created by Selim Mustafaev on 30.04.2025.
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
import UIKit
final class TabBarControllerDelegate: NSObject, UITabBarControllerDelegate {
static let shared = TabBarControllerDelegate()
var action: (() -> Void)?
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
guard let index = tabBarController.viewControllers?.firstIndex(of: viewController) else {
return true
}
// Do not select middle [pseudo]tab
if index == 2 {
action?()
return false
} else {
return true
}
}
}