draft2
This commit is contained in:
parent
20d9a596d7
commit
502aaf51f0
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,11 @@
|
||||
|
||||
import SwiftUI
|
||||
import Shared
|
||||
|
||||
// MARK: - BottomBar
|
||||
struct BottomBar: View {
|
||||
// Use meaningful tab names
|
||||
@State private var selectedTab: Tab = .today
|
||||
|
||||
// Define Tabs with associated icons and names
|
||||
enum Tab: CaseIterable {
|
||||
case today, weekly, settings
|
||||
|
||||
@ -28,69 +28,61 @@ struct BottomBar: View {
|
||||
|
||||
var body: some View {
|
||||
TabView(selection: $selectedTab) {
|
||||
// Use ContentView for the "Today" tab
|
||||
ContentView()
|
||||
.tag(Tab.today)
|
||||
.tabItem { Label(Tab.today.title, systemImage: Tab.today.iconName) }
|
||||
|
||||
// Placeholder for Weekly view
|
||||
WeeklyView()
|
||||
.tag(Tab.weekly)
|
||||
.tabItem { Label(Tab.weekly.title, systemImage: Tab.weekly.iconName) }
|
||||
|
||||
// Placeholder for Settings view
|
||||
SettingsView()
|
||||
.tag(Tab.settings)
|
||||
.tabItem { Label(Tab.settings.title, systemImage: Tab.settings.iconName) }
|
||||
}
|
||||
.accentColor(.purple) // Example: Set a custom accent color for the tab bar
|
||||
.accentColor(.purple)
|
||||
}
|
||||
}
|
||||
|
||||
// --- Weekly View ---
|
||||
// MARK: - WeeklyView
|
||||
struct WeeklyView: View {
|
||||
// Placeholder data for weekly usage (e.g., hours per day)
|
||||
let weeklyData: [Double] = [3.5, 4.2, 5.1, 2.8, 6.0, 7.5, 4.8]
|
||||
let days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
||||
let goalHours: Double = 8.0 // Example daily goal
|
||||
let goalHours: Double = 8.0
|
||||
|
||||
// Calculate max value for chart scaling
|
||||
var maxValue: Double {
|
||||
(weeklyData.max() ?? goalHours) * 1.1 // Add 10% buffer
|
||||
(weeklyData.max() ?? goalHours) * 1.1
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
// Use List for standard iOS layout
|
||||
List {
|
||||
Section("Usage Trend") {
|
||||
// Bar Chart Visualization
|
||||
HStack(alignment: .bottom, spacing: 15) { // Increased spacing
|
||||
HStack(alignment: .bottom, spacing: 15) {
|
||||
ForEach(0..<weeklyData.count, id: \.self) { index in
|
||||
VStack(spacing: 4) { // Spacing within the bar stack
|
||||
VStack(spacing: 4) {
|
||||
Text(String(format: "%.1fh", weeklyData[index]))
|
||||
.font(.caption)
|
||||
.foregroundColor(.accentColor)
|
||||
.lineLimit(1)
|
||||
.rotationEffect(.degrees(-90)) // Rotate text for better fit if needed
|
||||
.offset(y: -25) // Adjust offset if rotated
|
||||
.frame(height: 50) // Give space for text
|
||||
.rotationEffect(.degrees(-90))
|
||||
.offset(y: -25)
|
||||
.frame(height: 50)
|
||||
|
||||
Rectangle()
|
||||
.fill(weeklyData[index] > goalHours ? Color.orange : Color.accentColor) // Highlight days over goal
|
||||
// Scale height relative to the max value
|
||||
.frame(height: max(1, CGFloat(weeklyData[index] / maxValue) * 150)) // Ensure min height, scale based on max
|
||||
.cornerRadius(5) // Rounded corners for bars
|
||||
.fill(weeklyData[index] > goalHours ? Color.orange : Color.accentColor)
|
||||
.frame(height: max(1, CGFloat(weeklyData[index] / maxValue) * 150))
|
||||
.cornerRadius(5)
|
||||
|
||||
Text(days[index])
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.frame(maxWidth: .infinity) // Allow bars to take equal width
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
.frame(height: 220) // Adjust overall chart height
|
||||
.padding(.vertical) // Add padding around the chart
|
||||
.frame(height: 220)
|
||||
.padding(.vertical)
|
||||
}
|
||||
|
||||
Section("Summary") {
|
||||
@ -114,33 +106,54 @@ struct WeeklyView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.listStyle(.insetGrouped) // Use inset grouped style
|
||||
.listStyle(.insetGrouped)
|
||||
.navigationTitle("Weekly Stats")
|
||||
}
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
|
||||
// Helper function to calculate weekly average
|
||||
func calculateWeeklyAverage() -> String {
|
||||
let totalHours = weeklyData.reduce(0, +)
|
||||
let averageHours = totalHours / Double(weeklyData.count)
|
||||
let formatter = DateComponentsFormatter()
|
||||
formatter.allowedUnits = [.hour, .minute]
|
||||
formatter.unitsStyle = .abbreviated
|
||||
// Convert hours to seconds for formatter
|
||||
return formatter.string(from: TimeInterval(averageHours * 3600)) ?? "0m"
|
||||
}
|
||||
|
||||
// Helper property for days over goal
|
||||
var daysOverGoalCount: Int {
|
||||
weeklyData.filter { $0 > goalHours }.count
|
||||
}
|
||||
}
|
||||
|
||||
// --- Settings View ---
|
||||
// MARK: - GreetingViewModel
|
||||
class GreetingViewModel: ObservableObject {
|
||||
@Published var greetingText = "加载中..."
|
||||
private let greeting = Greeting()
|
||||
|
||||
func loadGreeting() {
|
||||
greetingText = "加载中..."
|
||||
|
||||
Task {
|
||||
do {
|
||||
let result = try await greeting.greet()
|
||||
await MainActor.run {
|
||||
self.greetingText = result
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
self.greetingText = "错误: \(error.localizedDescription)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SettingsView
|
||||
struct SettingsView: View {
|
||||
@StateObject private var viewModel = GreetingViewModel()
|
||||
@State private var usageReminders = true
|
||||
@State private var darkModeEnabled = false // Example state
|
||||
@State private var darkModeEnabled = false
|
||||
@State private var selectedLimit = "No Limit"
|
||||
let appLimits = ["No Limit", "1 hour", "2 hours", "Custom"]
|
||||
|
||||
@ -149,7 +162,7 @@ struct SettingsView: View {
|
||||
Form {
|
||||
Section("Notifications") {
|
||||
Toggle("Usage Reminders", isOn: $usageReminders)
|
||||
Toggle("Goal Achievement Alerts", isOn: .constant(false)) // Added toggle
|
||||
Toggle("Goal Achievement Alerts", isOn: .constant(false))
|
||||
}
|
||||
|
||||
Section("Usage Limits") {
|
||||
@ -158,11 +171,11 @@ struct SettingsView: View {
|
||||
Text($0)
|
||||
}
|
||||
}
|
||||
NavigationLink("App Specific Limits", destination: Text("App Limits Detail (Placeholder)")) // Added link
|
||||
NavigationLink("App Specific Limits", destination: Text("App Limits Detail (Placeholder)"))
|
||||
}
|
||||
|
||||
Section("Appearance") {
|
||||
Toggle("Dark Mode", isOn: $darkModeEnabled) // Added toggle
|
||||
Toggle("Dark Mode", isOn: $darkModeEnabled)
|
||||
NavigationLink("Accent Color", destination: Text("Color Picker (Placeholder)"))
|
||||
}
|
||||
|
||||
@ -175,11 +188,21 @@ struct SettingsView: View {
|
||||
}
|
||||
NavigationLink("Privacy Policy", destination: Text("Privacy Policy Details (Placeholder)"))
|
||||
}
|
||||
Section("test") {
|
||||
Text("Hello From Kotlin Multiplatform: \n\(Greeting().greet()) ")
|
||||
|
||||
Section("Kotlin Multiplatform 测试") {
|
||||
Text("来自KMP的问候:\n\(viewModel.greetingText)")
|
||||
.padding(.vertical, 8)
|
||||
|
||||
Button("重新加载问候语") {
|
||||
viewModel.loadGreeting()
|
||||
}
|
||||
.foregroundColor(.accentColor)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Settings")
|
||||
.onAppear {
|
||||
viewModel.loadGreeting()
|
||||
}
|
||||
}
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user