diff --git a/ios/WatchRunner Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/WatchRunner Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json index 49c81cd8..110a3e31 100644 --- a/ios/WatchRunner Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/WatchRunner Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,6 +1,7 @@ { "images" : [ { + "filename" : "icon.png", "idiom" : "universal", "platform" : "watchos", "size" : "1024x1024" diff --git a/ios/WatchRunner Watch App/Assets.xcassets/AppIcon.appiconset/icon.png b/ios/WatchRunner Watch App/Assets.xcassets/AppIcon.appiconset/icon.png new file mode 100644 index 00000000..0eeb8c11 Binary files /dev/null and b/ios/WatchRunner Watch App/Assets.xcassets/AppIcon.appiconset/icon.png differ diff --git a/ios/WatchRunner Watch App/ViewModels/ActivityViewModel.swift b/ios/WatchRunner Watch App/ViewModels/ActivityViewModel.swift index c5a3fde2..0505004f 100644 --- a/ios/WatchRunner Watch App/ViewModels/ActivityViewModel.swift +++ b/ios/WatchRunner Watch App/ViewModels/ActivityViewModel.swift @@ -19,7 +19,8 @@ class ActivityViewModel: ObservableObject { private let networkService = NetworkService() let filter: String private var isMock = false - + private var hasFetched = false // Add this + init(filter: String, mockActivities: [SnActivity]? = nil) { self.filter = filter if let mockActivities = mockActivities { @@ -29,10 +30,11 @@ class ActivityViewModel: ObservableObject { } func fetchActivities(token: String, serverUrl: String) async { - if isMock { return } + if isMock || hasFetched { return } // Check hasFetched guard !isLoading else { return } isLoading = true errorMessage = nil + hasFetched = true // Set hasFetched do { let fetchedActivities = try await networkService.fetchActivities(filter: filter, token: token, serverUrl: serverUrl) @@ -40,6 +42,7 @@ class ActivityViewModel: ObservableObject { } catch { self.errorMessage = error.localizedDescription print("[watchOS] fetchActivities failed with error: \(error)") + hasFetched = false // Reset on error } isLoading = false diff --git a/ios/WatchRunner Watch App/Views/ActivityListView.swift b/ios/WatchRunner Watch App/Views/ActivityListView.swift index 8ac17ba3..8a126e13 100644 --- a/ios/WatchRunner Watch App/Views/ActivityListView.swift +++ b/ios/WatchRunner Watch App/Views/ActivityListView.swift @@ -12,11 +12,11 @@ import SwiftUI struct ActivityListView: View { @StateObject private var viewModel: ActivityViewModel @EnvironmentObject var appState: AppState - + init(filter: String, mockActivities: [SnActivity]? = nil) { _viewModel = StateObject(wrappedValue: ActivityViewModel(filter: filter, mockActivities: mockActivities)) } - + var body: some View { Group { if viewModel.isLoading { @@ -37,24 +37,27 @@ struct ActivityListView: View { switch activity.type { case "posts.new", "posts.new.replies": if case .post(let post) = activity.data { - NavigationLink(destination: PostDetailView(post: post)) { + NavigationLink( + destination: PostDetailView(post: post).environmentObject(appState) + ) { PostRowView(post: post) } } case "discovery": - if case .discovery(let discoveryData) = activity.data { - DiscoveryView(discoveryData: discoveryData) - } + if case .discovery(let discoveryData) = activity.data { + DiscoveryView(discoveryData: discoveryData) + } default: Text("Unknown activity type: \(activity.type)") } } } } - .task { - // Only fetch if appState is ready and token/serverUrl are available + .onAppear { if appState.isReady, let token = appState.token, let serverUrl = appState.serverUrl { - await viewModel.fetchActivities(token: token, serverUrl: serverUrl) + Task.detached { + await viewModel.fetchActivities(token: token, serverUrl: serverUrl) + } } } .navigationTitle(viewModel.filter) diff --git a/ios/WatchRunner Watch App/Views/ExploreView.swift b/ios/WatchRunner Watch App/Views/ExploreView.swift index d6b043de..1aca9bab 100644 --- a/ios/WatchRunner Watch App/Views/ExploreView.swift +++ b/ios/WatchRunner Watch App/Views/ExploreView.swift @@ -11,53 +11,49 @@ import SwiftUI struct ExploreView: View { @StateObject private var appState = AppState() @State private var isComposing = false + @State private var selectedTab: String = "Explore" var body: some View { NavigationStack { - Group { - if appState.isReady { - TabView { - NavigationStack { - ActivityListView(filter: "Explore") - } + if appState.isReady { + TabView(selection: $selectedTab) { + ActivityListView(filter: "Explore") + .tag("Explore") .tabItem { Label("Explore", systemImage: "safari") } - NavigationStack { - ActivityListView(filter: "Subscriptions") - } + ActivityListView(filter: "Subscriptions") + .tag("Subscriptions") .tabItem { Label("Subscriptions", systemImage: "star") } - NavigationStack { - ActivityListView(filter: "Friends") - } + ActivityListView(filter: "Friends") + .tag("Friends") .tabItem { Label("Friends", systemImage: "person.2") } - } - .environmentObject(appState) - } else { - ProgressView { Text("Connecting to phone...") } - .onAppear { - appState.requestData() + } + .navigationTitle(selectedTab) + .toolbar { + ToolbarItem(placement: .primaryAction) { + Button(action: { isComposing = true }) { + Label("Compose", systemImage: "plus") } - } - } - .navigationTitle("Explore") - .toolbar { - ToolbarItem(placement: .primaryAction) { - Button(action: { isComposing = true }) { - Label("Compose", systemImage: "plus") } } + .environmentObject(appState) + } else { + ProgressView { Text("Connecting to phone...") } + .onAppear { + appState.requestData() + } } - .sheet(isPresented: $isComposing) { - ComposePostView() - .environmentObject(appState) - } + } + .sheet(isPresented: $isComposing) { + ComposePostView() + .environmentObject(appState) } } } \ No newline at end of file