switcher theme in BM
This commit is contained in:
		
							parent
							
								
									27a6ce7ce3
								
							
						
					
					
						commit
						c5906f42b7
					
				
							
								
								
									
										53
									
								
								Shared/Services/ThemeManager.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								Shared/Services/ThemeManager.swift
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
			
		||||
import SwiftUI
 | 
			
		||||
 | 
			
		||||
// Enum to represent the three theme options
 | 
			
		||||
enum Theme: String, CaseIterable {
 | 
			
		||||
    case system = "System"
 | 
			
		||||
    case light = "Light"
 | 
			
		||||
    case dark = "Dark"
 | 
			
		||||
    
 | 
			
		||||
    var colorScheme: ColorScheme? {
 | 
			
		||||
        switch self {
 | 
			
		||||
        case .system:
 | 
			
		||||
            return nil
 | 
			
		||||
        case .light:
 | 
			
		||||
            return .light
 | 
			
		||||
        case .dark:
 | 
			
		||||
            return .dark
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Observable class to manage the theme state
 | 
			
		||||
class ThemeManager: ObservableObject {
 | 
			
		||||
    @AppStorage("selectedTheme") private var selectedThemeValue: String = Theme.system.rawValue
 | 
			
		||||
    
 | 
			
		||||
    @Published var theme: Theme
 | 
			
		||||
    
 | 
			
		||||
    init() {
 | 
			
		||||
        // Read directly from UserDefaults to avoid using self before initialization is complete.
 | 
			
		||||
        let storedThemeValue = UserDefaults.standard.string(forKey: "selectedTheme") ?? ""
 | 
			
		||||
        self.theme = Theme(rawValue: storedThemeValue) ?? .system
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    func setTheme(_ theme: Theme) {
 | 
			
		||||
        self.theme = theme
 | 
			
		||||
        selectedThemeValue = theme.rawValue
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // This will be called from the button
 | 
			
		||||
    func toggleTheme(from currentSystemScheme: ColorScheme) {
 | 
			
		||||
        let newTheme: Theme
 | 
			
		||||
        
 | 
			
		||||
        switch theme {
 | 
			
		||||
        case .system:
 | 
			
		||||
            // If system is active, toggle to the opposite of the current system theme
 | 
			
		||||
            newTheme = currentSystemScheme == .dark ? .light : .dark
 | 
			
		||||
        case .light:
 | 
			
		||||
            newTheme = .dark
 | 
			
		||||
        case .dark:
 | 
			
		||||
            newTheme = .light
 | 
			
		||||
        }
 | 
			
		||||
        setTheme(newTheme)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -62,6 +62,8 @@ struct SideMenuFooterButton: View {
 | 
			
		||||
// --- MAIN VIEW ---
 | 
			
		||||
 | 
			
		||||
struct SideMenuView: View {
 | 
			
		||||
    @EnvironmentObject var themeManager: ThemeManager
 | 
			
		||||
    @Environment(\.colorScheme) var colorScheme
 | 
			
		||||
    @Binding var isPresented: Bool
 | 
			
		||||
    @State private var isAccountListExpanded = false
 | 
			
		||||
 | 
			
		||||
@ -78,21 +80,49 @@ struct SideMenuView: View {
 | 
			
		||||
        Account(name: "Creative Profile", username: "@creative", isCurrent: false)
 | 
			
		||||
    ]
 | 
			
		||||
    
 | 
			
		||||
    private var themeToggleButton: some View {
 | 
			
		||||
        Button(action: {
 | 
			
		||||
            themeManager.toggleTheme(from: colorScheme)
 | 
			
		||||
        }) {
 | 
			
		||||
            Image(systemName: iconName)
 | 
			
		||||
                .font(.title2)
 | 
			
		||||
                .foregroundColor(.primary)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var iconName: String {
 | 
			
		||||
        let effectiveScheme: ColorScheme
 | 
			
		||||
        switch themeManager.theme {
 | 
			
		||||
        case .system:
 | 
			
		||||
            effectiveScheme = colorScheme
 | 
			
		||||
        case .light:
 | 
			
		||||
            effectiveScheme = .light
 | 
			
		||||
        case .dark:
 | 
			
		||||
            effectiveScheme = .dark
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        return effectiveScheme == .dark ? "moon.fill" : "sun.max.fill"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var body: some View {
 | 
			
		||||
        VStack(alignment: .leading, spacing: 0) {
 | 
			
		||||
            ScrollView {
 | 
			
		||||
                VStack(alignment: .leading, spacing: 0) { // Parent VStack
 | 
			
		||||
                    
 | 
			
		||||
                    // --- Header
 | 
			
		||||
                    Button(action: {  }) {
 | 
			
		||||
                        Image(systemName: "person.circle.fill")
 | 
			
		||||
                            .resizable()
 | 
			
		||||
                            .frame(width: 60, height: 60)
 | 
			
		||||
                            .foregroundColor(.gray)
 | 
			
		||||
                            .padding(.horizontal, 20)
 | 
			
		||||
                            .padding(.top, topPadding)
 | 
			
		||||
                            .padding(.bottom, 10)
 | 
			
		||||
                    // --- Header ---
 | 
			
		||||
                    HStack {
 | 
			
		||||
                        Button(action: {  }) {
 | 
			
		||||
                            Image(systemName: "person.circle.fill")
 | 
			
		||||
                                .resizable()
 | 
			
		||||
                                .frame(width: 60, height: 60)
 | 
			
		||||
                                .foregroundColor(.gray)
 | 
			
		||||
                        }
 | 
			
		||||
                        Spacer()
 | 
			
		||||
                        themeToggleButton
 | 
			
		||||
                    }
 | 
			
		||||
                    .padding(.horizontal, 20)
 | 
			
		||||
                    .padding(.top, topPadding)
 | 
			
		||||
                    .padding(.bottom, 10)
 | 
			
		||||
                    
 | 
			
		||||
                    // --- Header Button ---
 | 
			
		||||
                    Button(action: {
 | 
			
		||||
 | 
			
		||||
@ -7,31 +7,24 @@
 | 
			
		||||
 | 
			
		||||
import SwiftUI
 | 
			
		||||
 | 
			
		||||
//@AppStorage("isLoggedIn") var isLoggedIn: Bool = false
 | 
			
		||||
//@AppStorage("isDarkMode") private var isDarkMode: Bool = false
 | 
			
		||||
//@AppStorage("currentUser") var currentUser: String = ""
 | 
			
		||||
 | 
			
		||||
@main
 | 
			
		||||
struct volnahubApp: App {
 | 
			
		||||
    @AppStorage("isDarkMode") private var isDarkMode: Bool = true
 | 
			
		||||
    @StateObject private var themeManager = ThemeManager()
 | 
			
		||||
    @StateObject private var viewModel = LoginViewModel()
 | 
			
		||||
    
 | 
			
		||||
    var body: some Scene {
 | 
			
		||||
        WindowGroup {
 | 
			
		||||
            ZStack {
 | 
			
		||||
                Color(isDarkMode ? .black : .white) // ✅ Фон в зависимости от темы
 | 
			
		||||
 | 
			
		||||
                if viewModel.isLoading{
 | 
			
		||||
            Group {
 | 
			
		||||
                if viewModel.isLoading {
 | 
			
		||||
                    SplashScreenView()
 | 
			
		||||
                }else{
 | 
			
		||||
                    if viewModel.isLoggedIn {
 | 
			
		||||
                        MainView(viewModel: viewModel)
 | 
			
		||||
                    } else {
 | 
			
		||||
                        LoginView(viewModel: viewModel)
 | 
			
		||||
                    }
 | 
			
		||||
                } else if viewModel.isLoggedIn {
 | 
			
		||||
                    MainView(viewModel: viewModel)
 | 
			
		||||
                } else {
 | 
			
		||||
                    LoginView(viewModel: viewModel)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            .preferredColorScheme(isDarkMode ? .dark : .light)
 | 
			
		||||
            .environmentObject(themeManager)
 | 
			
		||||
            .preferredColorScheme(themeManager.theme.colorScheme)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -36,6 +36,7 @@
 | 
			
		||||
		1A9B01662E4BFA3600887E0B /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A9B01652E4BFA3600887E0B /* Media.xcassets */; };
 | 
			
		||||
		1A9B016E2E4BFB9000887E0B /* NewHomeTabViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9B016D2E4BFB9000887E0B /* NewHomeTabViewModel.swift */; };
 | 
			
		||||
		1A9B017C2E4C087F00887E0B /* SideMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9B017B2E4C087F00887E0B /* SideMenuView.swift */; };
 | 
			
		||||
		1A9E4FB32E4D6A67002249D6 /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9E4FB22E4D6A67002249D6 /* ThemeManager.swift */; };
 | 
			
		||||
		1AB4F8CD2E22E341002B6E40 /* AccountShareSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB4F8CC2E22E341002B6E40 /* AccountShareSheet.swift */; };
 | 
			
		||||
		1AB4F8F32E22EC9F002B6E40 /* FollowersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB4F8F22E22EC9F002B6E40 /* FollowersView.swift */; };
 | 
			
		||||
		1AB4F8F72E22ECAC002B6E40 /* FollowingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB4F8F62E22ECAC002B6E40 /* FollowingView.swift */; };
 | 
			
		||||
@ -90,6 +91,7 @@
 | 
			
		||||
		1A9B01652E4BFA3600887E0B /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
 | 
			
		||||
		1A9B016D2E4BFB9000887E0B /* NewHomeTabViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewHomeTabViewModel.swift; sourceTree = "<group>"; };
 | 
			
		||||
		1A9B017B2E4C087F00887E0B /* SideMenuView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideMenuView.swift; sourceTree = "<group>"; };
 | 
			
		||||
		1A9E4FB22E4D6A67002249D6 /* ThemeManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = "<group>"; };
 | 
			
		||||
		1AB4F8CC2E22E341002B6E40 /* AccountShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountShareSheet.swift; sourceTree = "<group>"; };
 | 
			
		||||
		1AB4F8F22E22EC9F002B6E40 /* FollowersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowersView.swift; sourceTree = "<group>"; };
 | 
			
		||||
		1AB4F8F62E22ECAC002B6E40 /* FollowingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingView.swift; sourceTree = "<group>"; };
 | 
			
		||||
@ -227,6 +229,7 @@
 | 
			
		||||
		1A7940E52DF7B341002569DA /* Services */ = {
 | 
			
		||||
			isa = PBXGroup;
 | 
			
		||||
			children = (
 | 
			
		||||
				1A9E4FB22E4D6A67002249D6 /* ThemeManager.swift */,
 | 
			
		||||
				1A7940E12DF7B1C5002569DA /* KeychainService.swift */,
 | 
			
		||||
			);
 | 
			
		||||
			path = Services;
 | 
			
		||||
@ -450,6 +453,7 @@
 | 
			
		||||
				1A7940E22DF7B1C5002569DA /* KeychainService.swift in Sources */,
 | 
			
		||||
				1A7940A62DF77DF5002569DA /* User.swift in Sources */,
 | 
			
		||||
				1A7940A22DF77DE9002569DA /* AuthService.swift in Sources */,
 | 
			
		||||
				1A9E4FB32E4D6A67002249D6 /* ThemeManager.swift in Sources */,
 | 
			
		||||
				1AEE5EB32E21A85800A3DCA3 /* SearchTab.swift in Sources */,
 | 
			
		||||
				1ACE61152E22FE2000B37AC5 /* PostDetailView.swift in Sources */,
 | 
			
		||||
				1ACE61192E22FF1400B37AC5 /* Post.swift in Sources */,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user