✨ App info header on watchOS
This commit is contained in:
		
							
								
								
									
										21
									
								
								ios/WatchRunner Watch App/Assets.xcassets/Logo.imageset/Contents.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								ios/WatchRunner Watch App/Assets.xcassets/Logo.imageset/Contents.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | { | ||||||
|  |   "images" : [ | ||||||
|  |     { | ||||||
|  |       "filename" : "icon.png", | ||||||
|  |       "idiom" : "universal", | ||||||
|  |       "scale" : "1x" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "idiom" : "universal", | ||||||
|  |       "scale" : "2x" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "idiom" : "universal", | ||||||
|  |       "scale" : "3x" | ||||||
|  |     } | ||||||
|  |   ], | ||||||
|  |   "info" : { | ||||||
|  |     "author" : "xcode", | ||||||
|  |     "version" : 1 | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								ios/WatchRunner Watch App/Assets.xcassets/Logo.imageset/icon.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ios/WatchRunner Watch App/Assets.xcassets/Logo.imageset/icon.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 70 KiB | 
| @@ -11,37 +11,35 @@ import SwiftUI | |||||||
| struct ContentView: View { | struct ContentView: View { | ||||||
|     @StateObject private var appState = AppState() |     @StateObject private var appState = AppState() | ||||||
|     @State private var selection: Panel? = .explore |     @State private var selection: Panel? = .explore | ||||||
|  |      | ||||||
|     enum Panel: Hashable { |     enum Panel: Hashable { | ||||||
|         case explore |         case explore | ||||||
|         case chat |         case chat | ||||||
|         case notifications |         case notifications | ||||||
|         case account |         case account | ||||||
|     } |     } | ||||||
|  |      | ||||||
|     var body: some View { |     var body: some View { | ||||||
|         NavigationSplitView { |         NavigationSplitView { | ||||||
|             List(selection: $selection) { |             List(selection: $selection) { | ||||||
|                 Label("Explore", systemImage: "globe").tag(Panel.explore) |                 AppInfoHeaderView().listRowBackground(Color.clear) | ||||||
|                 Label("Chat", systemImage: "message").tag(Panel.chat) |                  | ||||||
|                 Label("Notifications", systemImage: "bell").tag(Panel.notifications) |                 Label("Explore", systemImage: "globe.fill").tag(Panel.explore) | ||||||
|                 Label("Account", systemImage: "person.circle").tag(Panel.account) |                 Label("Chat", systemImage: "message.fill").tag(Panel.chat) | ||||||
|  |                 Label("Notifications", systemImage: "bell.fill").tag(Panel.notifications) | ||||||
|  |                 Label("Account", systemImage: "person.circle.fill").tag(Panel.account) | ||||||
|             } |             } | ||||||
|             .listStyle(.automatic) |             .listStyle(.automatic) | ||||||
|         } detail: { |         } detail: { | ||||||
|             switch selection { |             switch selection { | ||||||
|             case .explore: |             case .explore: | ||||||
|                 ExploreView() |                 ExploreView().environmentObject(appState) | ||||||
|                     .environmentObject(appState) |  | ||||||
|             case .chat: |             case .chat: | ||||||
|                 ChatView() |                 ChatView().environmentObject(appState) | ||||||
|                     .environmentObject(appState) |  | ||||||
|             case .notifications: |             case .notifications: | ||||||
|                 NotificationView() |                 NotificationView().environmentObject(appState) | ||||||
|                     .environmentObject(appState) |  | ||||||
|             case .account: |             case .account: | ||||||
|                 AccountView() |                 AccountView().environmentObject(appState) | ||||||
|                     .environmentObject(appState) |  | ||||||
|             case .none: |             case .none: | ||||||
|                 Text("Select a panel") |                 Text("Select a panel") | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -58,9 +58,8 @@ class ImageLoader: ObservableObject { | |||||||
|                 switch result { |                 switch result { | ||||||
|                 case .success(let value): |                 case .success(let value): | ||||||
|                     self.image = Image(uiImage: value.image) |                     self.image = Image(uiImage: value.image) | ||||||
|                     print("[watchOS] Image loaded successfully from \(value.cacheType == .none ? "network" : "cache (\(value.cacheType))").") |  | ||||||
|                     self.isLoading = false |                     self.isLoading = false | ||||||
|                 case .failure(let error): |                 case .failure(_): | ||||||
|                     // If WebP processor fails (likely due to format), try with default processor |                     // If WebP processor fails (likely due to format), try with default processor | ||||||
|                     let defaultProcessor = DefaultImageProcessor.default |                     let defaultProcessor = DefaultImageProcessor.default | ||||||
|                     self.currentTask = KingfisherManager.shared.retrieveImage( |                     self.currentTask = KingfisherManager.shared.retrieveImage( | ||||||
| @@ -78,7 +77,6 @@ class ImageLoader: ObservableObject { | |||||||
|                             switch fallbackResult { |                             switch fallbackResult { | ||||||
|                             case .success(let value): |                             case .success(let value): | ||||||
|                                 self.image = Image(uiImage: value.image) |                                 self.image = Image(uiImage: value.image) | ||||||
|                                 print("[watchOS] Image loaded successfully from \(value.cacheType == .none ? "network" : "cache (\(value.cacheType))") using fallback processor.") |  | ||||||
|                             case .failure(let fallbackError): |                             case .failure(let fallbackError): | ||||||
|                                 self.errorMessage = fallbackError.localizedDescription |                                 self.errorMessage = fallbackError.localizedDescription | ||||||
|                                 print("[watchOS] Image loading failed: \(fallbackError.localizedDescription)") |                                 print("[watchOS] Image loading failed: \(fallbackError.localizedDescription)") | ||||||
|   | |||||||
| @@ -380,16 +380,16 @@ class NetworkService { | |||||||
|             print(context) |             print(context) | ||||||
|             return [] |             return [] | ||||||
|         } catch DecodingError.keyNotFound(let key, let context) { |         } catch DecodingError.keyNotFound(let key, let context) { | ||||||
|             print("Key '\(key)' not found:", context.debugDescription) |             print("[watchOS] Message decode failed: Key '\(key)' not found:", context.debugDescription) | ||||||
|             print("codingPath:", context.codingPath) |             print("[watchOS] Message decode failed: codingPath:", context.codingPath) | ||||||
|             return [] |             return [] | ||||||
|         } catch DecodingError.valueNotFound(let value, let context) { |         } catch DecodingError.valueNotFound(let value, let context) { | ||||||
|             print("Value '\(value)' not found:", context.debugDescription) |             print("[watchOS] Message decode failed: Value '\(value)' not found:", context.debugDescription) | ||||||
|             print("codingPath:", context.codingPath) |             print("[watchOS] Message decode failed: codingPath:", context.codingPath) | ||||||
|             return [] |             return [] | ||||||
|         } catch DecodingError.typeMismatch(let type, let context) { |         } catch DecodingError.typeMismatch(let type, let context) { | ||||||
|             print("Type '\(type)' mismatch:", context.debugDescription) |             print("[watchOS] Message decode failed: Type '\(type)' mismatch:", context.debugDescription) | ||||||
|             print("codingPath:", context.codingPath) |             print("[watchOS] Message decode failed: codingPath:", context.codingPath) | ||||||
|             return [] |             return [] | ||||||
|         } catch { |         } catch { | ||||||
|             print("error: ", error) |             print("error: ", error) | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								ios/WatchRunner Watch App/Views/AppInfoHeaderView.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								ios/WatchRunner Watch App/Views/AppInfoHeaderView.swift
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | // | ||||||
|  | //  AppInfoHeader.swift | ||||||
|  | //  Runner | ||||||
|  | // | ||||||
|  | //  Created by LittleSheep on 2025/10/30. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | import SwiftUI | ||||||
|  |  | ||||||
|  | struct AppInfoHeaderView : View { | ||||||
|  |     var body: some View { | ||||||
|  |         VStack(alignment: .leading) { | ||||||
|  |             HStack(spacing: 12) { | ||||||
|  |                 Image("Logo") | ||||||
|  |                     .resizable() | ||||||
|  |                     .frame(width: 40, height: 40) | ||||||
|  |                  | ||||||
|  |                 VStack(alignment: .leading) { | ||||||
|  |                     Text("Solian").font(.headline) | ||||||
|  |                     Text("for Apple Watch").font(.system(size: 11)) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user