Files
Reflect/Shared/Views/Sharing/SharingListView.swift
Trey T ed8205cd88 Complete accessibility identifier coverage across all 152 project files
Exhaustive file-by-file audit of every Swift file in the project (iOS app,
Watch app, Widget extension). Every interactive UI element — buttons, toggles,
pickers, links, menus, tap gestures, text editors, color pickers, photo
pickers — now has an accessibilityIdentifier for XCUITest automation.

46 files changed across Shared/, Onboarding/, Watch App/, and Widget targets.
Added ~100 new ID definitions covering settings debug controls, export/photo
views, sharing templates, customization subviews, onboarding flows, tip
modals, widget voting buttons, and watch mood buttons.
2026-03-26 08:34:56 -05:00

213 lines
8.6 KiB
Swift

//
// SharingView.swift
// Reflect (iOS)
//
// Created by Trey Tartt on 2/6/22.
//
import SwiftUI
struct WrappedSharable: Hashable, Equatable {
static func == (lhs: WrappedSharable, rhs: WrappedSharable) -> Bool {
lhs.id == rhs.id && lhs.description == rhs.description
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
let id = UUID()
let preview: AnyView
let destination: AnyView
let description: String
}
struct SharingListView: View {
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
private var textColor: Color { theme.currentTheme.labelColor }
class ShareStateViewModel: ObservableObject {
@Published var selectedItem: WrappedSharable? = nil
@Published var showSheet = false
}
@StateObject private var selectedShare = ShareStateViewModel()
var sharebleItems = [WrappedSharable]()
@MainActor
init() {
let earliestDate = DataController.shared.earliestEntry?.forDate ?? Date()
let now = Date()
let tenDaysAgo = Calendar.current.date(byAdding: .day, value: -10, to: now)!
let monthStart = now.startOfMonth
let monthEnd = now.endOfMonth
// All Moods
let allMoodsEntries = DataController.shared.getData(startDate: earliestDate, endDate: now, includedDays: [1,2,3,4,5,6,7])
let allMoodsMetrics = Random.createTotalPerc(fromEntries: allMoodsEntries)
let allMoodsCount = allMoodsEntries.count
// Current Streak (Last 10 Days)
let streakEntries = DataController.shared.getData(startDate: tenDaysAgo, endDate: now, includedDays: [1,2,3,4,5,6,7])
// Month Total
let monthEntries = DataController.shared.getData(startDate: monthStart, endDate: monthEnd, includedDays: [1,2,3,4,5,6,7])
let monthMetrics = Random.createTotalPerc(fromEntries: monthEntries)
let month = Calendar.current.component(.month, from: now)
self.sharebleItems = [
// All Time Moods style picker with 2 variations
WrappedSharable(
preview: AnyView(
AllMoodsTotalTemplate(isPreview: true, startDate: earliestDate, endDate: now, fakeData: false)
),
destination: AnyView(
SharingStylePickerView(title: "All Time Moods", designs: [
SharingDesign(
name: "Gradient",
shareView: AnyView(AllMoodsV2(metrics: allMoodsMetrics, totalCount: allMoodsCount)),
image: { AllMoodsV2(metrics: allMoodsMetrics, totalCount: allMoodsCount).image }
),
SharingDesign(
name: "Color Block",
shareView: AnyView(AllMoodsV5(metrics: allMoodsMetrics, totalCount: allMoodsCount)),
image: { AllMoodsV5(metrics: allMoodsMetrics, totalCount: allMoodsCount).image }
),
])
),
description: AllMoodsTotalTemplate.description
),
//////////////////////////////////////////////////////////
// Last 10 Days style picker with 2 variations
WrappedSharable(
preview: AnyView(
CurrentStreakTemplate(isPreview: true, startDate: tenDaysAgo, endDate: now, fakeData: false)
),
destination: AnyView(
SharingStylePickerView(title: "Last 10 Days", designs: [
SharingDesign(
name: "Gradient Cards",
shareView: AnyView(CurrentStreakV2(moodEntries: streakEntries)),
image: { CurrentStreakV2(moodEntries: streakEntries).image }
),
SharingDesign(
name: "Color Strips",
shareView: AnyView(CurrentStreakV5(moodEntries: streakEntries)),
image: { CurrentStreakV5(moodEntries: streakEntries).image }
),
])
),
description: CurrentStreakTemplate.description
),
//////////////////////////////////////////////////////////
// Longest Streak custom picker with mood selection
WrappedSharable(
preview: AnyView(
LongestStreakTemplate(isPreview: true, startDate: earliestDate, endDate: now, fakeData: false)
),
destination: AnyView(
LongestStreakPickerView(startDate: earliestDate, endDate: now)
),
description: LongestStreakTemplate.description
),
//////////////////////////////////////////////////////////
// This Month style picker with 2 variations
WrappedSharable(
preview: AnyView(
MonthTotalTemplate(isPreview: true, startDate: monthStart, endDate: monthEnd, fakeData: false)
),
destination: AnyView(
SharingStylePickerView(title: "This Month", designs: [
SharingDesign(
name: "Clean Calendar",
shareView: AnyView(MonthTotalV1(moodMetrics: monthMetrics, moodEntries: monthEntries, month: month)),
image: { MonthTotalV1(moodMetrics: monthMetrics, moodEntries: monthEntries, month: month).image }
),
SharingDesign(
name: "Stacked Bars",
shareView: AnyView(MonthTotalV5(moodMetrics: monthMetrics, moodEntries: monthEntries, month: month)),
image: { MonthTotalV5(moodMetrics: monthMetrics, moodEntries: monthEntries, month: month).image }
),
])
),
description: MonthTotalTemplate.description
),
//////////////////////////////////////////////////////////
]
}
func didDismiss() {
selectedShare.showSheet = false
selectedShare.selectedItem = nil
}
var body: some View {
VStack {
ScrollView {
ForEach(sharebleItems, id: \.self) { item in
Button(action: {
selectedShare.selectedItem = item
selectedShare.showSheet = true
}, label: {
ZStack {
theme.currentTheme.secondaryBGColor
item.preview
.frame(height: 88)
VStack {
Spacer()
Text(item.description)
.font(.title)
.foregroundColor(textColor)
.fontWeight(.bold)
.frame(minWidth: 0, maxWidth: .infinity)
.frame(height: 44)
.background(
theme.currentTheme.secondaryBGColor
)
.opacity(0.9)
}
}
.frame(height: 88)
.cornerRadius(Constants.viewsCornerRaidus, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
.scaledToFill()
.clipped()
.contentShape(Rectangle())
.padding([.leading, .trailing])
})
.accessibilityIdentifier(AccessibilityID.Sharing.templateButton(item.description))
}
}
}
.padding([.top, .bottom])
.background(
theme.currentTheme.bg
.edgesIgnoringSafeArea(.top)
)
.sheet(isPresented: $selectedShare.showSheet,
onDismiss: didDismiss) {
selectedShare.selectedItem?.destination
}
}
func share(image: UIImage) {
}
}
struct SharingView_Previews: PreviewProvider {
static var previews: some View {
Group {
SharingListView()
SharingListView()
.preferredColorScheme(.dark)
}
}
}