Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions SwiftLeeds.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@
0B4CB3FC28EAF7C500246E62 /* CachedAsyncImage in Frameworks */ = {isa = PBXBuildFile; productRef = 0B4CB3FB28EAF7C500246E62 /* CachedAsyncImage */; };
0B4CB3FD28EAF7FE00246E62 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AECB295A27417F9E00CDC983 /* Assets.xcassets */; };
0B4CB3FE28EAF80200246E62 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AECB29872741ACE000CDC983 /* Colors.xcassets */; };
0B59B5652E70E5D400820C3C /* TeamMember.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B59B5642E70E5D400820C3C /* TeamMember.swift */; };
0B59B5662E70E5D400820C3C /* TeamMember.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B59B5642E70E5D400820C3C /* TeamMember.swift */; };
0B59B5672E70E5D400820C3C /* TeamMember.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B59B5642E70E5D400820C3C /* TeamMember.swift */; };
0B59B5692E70E5FE00820C3C /* TeamMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B59B5682E70E5FE00820C3C /* TeamMemberView.swift */; };
0B59B56B2E70E6AC00820C3C /* CompactActionItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B59B56A2E70E6AC00820C3C /* CompactActionItem.swift */; };
0B59B56E2E70EA4F00820C3C /* about.json in Resources */ = {isa = PBXBuildFile; fileRef = 0B59B56C2E70EA4F00820C3C /* about.json */; };
0B59B56F2E70EA4F00820C3C /* AboutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B59B56D2E70EA4F00820C3C /* AboutViewModel.swift */; };
0B59B5712E70EA6600820C3C /* About.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B59B5702E70EA6600820C3C /* About.swift */; };
0B59B5722E70EA6600820C3C /* About.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B59B5702E70EA6600820C3C /* About.swift */; };
0B59B5732E70EA6600820C3C /* About.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B59B5702E70EA6600820C3C /* About.swift */; };
0B910A352A48FEC100648B32 /* SponsorTileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA57DE4E2875B09900911F03 /* SponsorTileView.swift */; };
0B910A372A49D07700648B32 /* Sponsor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B910A362A49D07700648B32 /* Sponsor.swift */; };
0B910A382A49D09300648B32 /* Sponsor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B910A362A49D07700648B32 /* Sponsor.swift */; };
Expand Down Expand Up @@ -209,6 +219,12 @@
0B4CB3CE28EAF19100246E62 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
0B4CB3D028EAF19100246E62 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0B4CB3D128EAF19100246E62 /* SwiftLeedsAppClip.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SwiftLeedsAppClip.entitlements; sourceTree = "<group>"; };
0B59B5642E70E5D400820C3C /* TeamMember.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeamMember.swift; sourceTree = "<group>"; };
0B59B5682E70E5FE00820C3C /* TeamMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeamMemberView.swift; sourceTree = "<group>"; };
0B59B56A2E70E6AC00820C3C /* CompactActionItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactActionItem.swift; sourceTree = "<group>"; };
0B59B56C2E70EA4F00820C3C /* about.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = about.json; sourceTree = "<group>"; };
0B59B56D2E70EA4F00820C3C /* AboutViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewModel.swift; sourceTree = "<group>"; };
0B59B5702E70EA6600820C3C /* About.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = About.swift; sourceTree = "<group>"; };
0B910A362A49D07700648B32 /* Sponsor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sponsor.swift; sourceTree = "<group>"; };
2A3831112884A96600030002 /* FancyHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FancyHeaderView.swift; sourceTree = "<group>"; };
39345FD9288F17EE0031BCFF /* BottomSheetView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BottomSheetView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -531,7 +547,11 @@
AED26F7628676A9200E06064 /* About */ = {
isa = PBXGroup;
children = (
0B59B56C2E70EA4F00820C3C /* about.json */,
AED26F7728676A9900E06064 /* AboutView.swift */,
0B59B56D2E70EA4F00820C3C /* AboutViewModel.swift */,
0B59B56A2E70E6AC00820C3C /* CompactActionItem.swift */,
0B59B5682E70E5FE00820C3C /* TeamMemberView.swift */,
);
path = About;
sourceTree = "<group>";
Expand Down Expand Up @@ -613,12 +633,14 @@
FA57DE572875B0E300911F03 /* Model */ = {
isa = PBXGroup;
children = (
0B59B5702E70EA6600820C3C /* About.swift */,
AE8C1B2128BFCF4700AF7318 /* Activity.swift */,
FA534D8128A1909300A3BFBB /* Local.swift */,
AE8C1B2328BFCFC700AF7318 /* Presentation.swift */,
AEDC22542898288F00746247 /* Schedule.swift */,
AE8C1B2528BFCFE700AF7318 /* Speaker.swift */,
0B910A362A49D07700648B32 /* Sponsor.swift */,
0B59B5642E70E5D400820C3C /* TeamMember.swift */,
);
path = Model;
sourceTree = "<group>";
Expand Down Expand Up @@ -829,6 +851,7 @@
AE1C801428A7BCD000996659 /* Settings.bundle in Resources */,
AECB29882741ACE000CDC983 /* Colors.xcassets in Resources */,
AECB295E27417F9E00CDC983 /* Preview Assets.xcassets in Resources */,
0B59B56E2E70EA4F00820C3C /* about.json in Resources */,
AECB295B27417F9E00CDC983 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -867,6 +890,7 @@
0B4CB3EC28EAF5E900246E62 /* ActivityView.swift in Sources */,
0B4CB3F228EAF61600246E62 /* WebView.swift in Sources */,
E3569B052E5B902B00BC9556 /* UserDefaultsKeys.swift in Sources */,
0B59B5712E70EA6600820C3C /* About.swift in Sources */,
AE1CDBF02AC05B2B00E83420 /* HttpMethod.swift in Sources */,
0B4B1A512A48FB6400ED7EA9 /* SponsorsViewModel.swift in Sources */,
0B4CB3EA28EAF5D900246E62 /* Color.swift in Sources */,
Expand All @@ -891,6 +915,7 @@
0B4CB3EB28EAF5E300246E62 /* TalkCell.swift in Sources */,
AE1CDBEE2AC05B2B00E83420 /* Requests.swift in Sources */,
740162DB2A7053A000C2D1B3 /* AppState.swift in Sources */,
0B59B5652E70E5D400820C3C /* TeamMember.swift in Sources */,
0B910A382A49D09300648B32 /* Sponsor.swift in Sources */,
0B4CB3F428EAF62100246E62 /* CommonTileView.swift in Sources */,
0B4CB3C828EAF19100246E62 /* SwiftLeedsAppClipApp.swift in Sources */,
Expand All @@ -908,6 +933,7 @@
74E62F7428CAAB30004422F9 /* SwiftLeedsMediumWidgetView.swift in Sources */,
74E62F7228CA98EA004422F9 /* SwiftLeedsSmallWidgetView.swift in Sources */,
7406572928E240720087F44F /* WidgetConstants.swift in Sources */,
0B59B5672E70E5D400820C3C /* TeamMember.swift in Sources */,
74A09FF228C689AB00E03F39 /* Color.swift in Sources */,
AE9367982A9357D000F2DB3F /* Helper.swift in Sources */,
74B14FB028CE21D7004C0A40 /* TimeineProvider.swift in Sources */,
Expand All @@ -917,6 +943,7 @@
74B14FB228CE2221004C0A40 /* SwiftLeedsWidgetEntry.swift in Sources */,
74E62F7028CA68D2004422F9 /* Constants.swift in Sources */,
74B14FB428CE2245004C0A40 /* SwiftLeedsWidgetEntryView.swift in Sources */,
0B59B5732E70EA6600820C3C /* About.swift in Sources */,
7406572728E2304E0087F44F /* Calendar.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -928,8 +955,10 @@
AEDC22532898281300746247 /* MyConferenceViewModel.swift in Sources */,
AED26F7828676A9900E06064 /* AboutView.swift in Sources */,
FA57DE502875B09900911F03 /* SponsorTileView.swift in Sources */,
0B59B5692E70E5FE00820C3C /* TeamMemberView.swift in Sources */,
394653AB288BB7C800212E1C /* SpeakerView.swift in Sources */,
E3569B002E5A55D000BC9556 /* UserDefaultsKeys.swift in Sources */,
0B59B56F2E70EA4F00820C3C /* AboutViewModel.swift in Sources */,
FA57DE4D2875B08600911F03 /* LinearGradient.swift in Sources */,
394653A9288BB47A00212E1C /* SectionHeader.swift in Sources */,
FA57DE552875B0C100911F03 /* SquishyButtonStyle.swift in Sources */,
Expand All @@ -948,6 +977,8 @@
2A3831122884A96600030002 /* FancyHeaderView.swift in Sources */,
E3569B082E5B905100BC9556 /* SettingsView.swift in Sources */,
FA57DE4B2875B06B00911F03 /* SwiftLeedsContainer.swift in Sources */,
0B59B5722E70EA6600820C3C /* About.swift in Sources */,
0B59B56B2E70E6AC00820C3C /* CompactActionItem.swift in Sources */,
74F5EF892A49CECB008D9413 /* SidebarView.swift in Sources */,
FAAB819128844EBC001159BB /* View+MeasureSize.swift in Sources */,
E3569AF92E5A301D00BC9556 /* ThemeManager.swift in Sources */,
Expand All @@ -962,6 +993,7 @@
E3569AEF2E5A1D0200BC9556 /* ShimmerView.swift in Sources */,
0B4B1A4D2A486EA800ED7EA9 /* SponsorsViewModel.swift in Sources */,
AECB295727417F9D00CDC983 /* SwiftLeedsApp.swift in Sources */,
0B59B5662E70E5D400820C3C /* TeamMember.swift in Sources */,
0B4B1A4B2A4858F600ED7EA9 /* SponsorsView.swift in Sources */,
AE8C1B2B28C4B39A00AF7318 /* TokenDetails.swift in Sources */,
0B910A372A49D07700648B32 /* Sponsor.swift in Sources */,
Expand Down
22 changes: 22 additions & 0 deletions SwiftLeeds/Data/Model/About.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// About.swift
// SwiftLeeds
//
// Created by Muralidharan Kathiresan on 10/09/2025.
//

import Foundation

struct AboutURLs: Codable {
let venue: String
let codeOfConduct: String
let reportAProblem: String
let slack: String
let youtube: String
}

struct AboutData: Codable {
let urls: AboutURLs
let truncatedAboutText: String
let teamMembers: [TeamMember]
}
19 changes: 19 additions & 0 deletions SwiftLeeds/Data/Model/TeamMember.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// File.swift
// SwiftLeeds
//
// Created by Muralidharan Kathiresan on 09/09/2025.
//

import Foundation

struct TeamMember: Codable, Identifiable {
let name: String
let role: String?
let linkedInURL: String?
let twitterURL: String?
let slackURL: String?
let photoURL: String?

var id: String { name }
}
96 changes: 43 additions & 53 deletions SwiftLeeds/Views/About/AboutView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,12 @@

import SwiftUI
import ReadabilityModifier
import CachedAsyncImage

struct AboutView: View {
@StateObject private var viewModel = AboutViewModel()
@State private var isReportAProblemShown = false
@State private var isFullAboutShown = false

private let venueURL = URL(string: "https://swiftleeds.co.uk/#venue")
private let codeOfConductURL = URL(string: "https://swiftleeds.co.uk/conduct")
private let reportAProblemLink = "https://forms.gle/PJie9aRNAtzQUdUu9"
private let slackURL = URL(string: "https://join.slack.com/t/swiftleedsworkspace/shared_invite/zt-3dex3vb3k-JNYQ~ollX6R619D_tZVfXQ")
private let youtubeURL = URL(string: "https://www.youtube.com/@swiftleeds")

private let truncatedAboutText = """
Adam Rush founded SwiftLeeds in 2019, born from over ten years of experience attending conferences. The inspiration was bringing a modern, inclusive conference in the North of the UK to be more accessible for all.

SwiftLeeds is now run with over ten community volunteers building the website, iOS applications...
"""

private var gridColumns: [GridItem] {
#if os(iOS)
Expand All @@ -32,6 +22,15 @@ struct AboutView: View {
#endif
return Array(repeating: GridItem(.flexible(), spacing: Padding.cellGap), count: columnCount)
}

private var teamGridColumns: [GridItem] {
#if os(iOS)
let columnCount = UIDevice.current.userInterfaceIdiom == .pad ? 3 : 2
#else
let columnCount = 2
#endif
Comment on lines +27 to +31
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this not be simplified without the if os(iOS) check since it defaults to 2 if it's not .pad anyhow? 🤔

return Array(repeating: GridItem(.flexible(), spacing: Padding.cellGap), count: columnCount)
}

var body: some View {
SwiftLeedsContainer {
Expand All @@ -56,7 +55,7 @@ struct AboutView: View {
.foregroundColor(.primary)

VStack(alignment: .leading, spacing: 8) {
Text(.init(truncatedAboutText))
Text(.init(viewModel.truncatedAboutText))
.font(.subheadline.weight(.regular))
.foregroundColor(.secondary)

Expand All @@ -78,12 +77,12 @@ struct AboutView: View {
in: RoundedRectangle(cornerRadius: Constants.cellRadius)
)
.accessibilityElement(children: .ignore)
.accessibilityLabel("About SwiftLeeds. \(truncatedAboutText). Tap More for full details.")
.accessibilityLabel("About SwiftLeeds. \(viewModel.truncatedAboutText). Tap More for full details.")

LazyVGrid(columns: gridColumns, spacing: Padding.cellGap) {
CompactActionItem(
icon: "exclamationmark.triangle.fill",
title: "Report\nProblem",
title: "Report a\nProblem",
accessibilityHint: "Opens a web view to allow a problem to be reported",
action: { isReportAProblemShown = true }
)
Expand All @@ -92,37 +91,61 @@ struct AboutView: View {
icon: "doc.text.fill",
title: "Code of\nConduct",
accessibilityHint: "Opens a web page showing our code of conduct",
action: { openURL(url: codeOfConductURL) }
action: { openURL(url: viewModel.codeOfConductURL) }
)

CompactActionItem(
icon: "location.fill",
title: "Venue\nInfo",
accessibilityHint: "Opens a web page showing our venue information",
action: { openURL(url: venueURL) }
action: { openURL(url: viewModel.venueURL) }
)

CompactActionItem(
icon: "message.fill",
title: "Join our\nSlack",
accessibilityHint: "Opens an invite link to join the SwiftLeeds Slack workspace",
action: { openURL(url: slackURL) }
action: { openURL(url: viewModel.slackURL) }
)

CompactActionItem(
icon: "play.rectangle.fill",
title: "YouTube\nChannel",
accessibilityHint: "Opens the SwiftLeeds YouTube channel",
action: { openURL(url: youtubeURL) }
action: { openURL(url: viewModel.youtubeURL) }
)
}
.padding(.vertical, 8)

VStack(alignment: .leading, spacing: Padding.stackGap) {
Text("Meet the Team")
.font(.headline.weight(.semibold))
.foregroundColor(.primary)

Text("Connect with our amazing volunteers who make SwiftLeeds possible")
.font(.subheadline)
.foregroundColor(.secondary)
}
.frame(maxWidth: .infinity, alignment: .leading)
.multilineTextAlignment(.leading)
.padding(Padding.cell)
.background(
Color.cellBackground,
in: RoundedRectangle(cornerRadius: Constants.cellRadius)
)

LazyVGrid(columns: teamGridColumns, spacing: Padding.cellGap) {
ForEach(viewModel.teamMembers) { member in
TeamMemberView(member: member)
}
}
.padding(.vertical, 8)
}
.fitToReadableContentGuide(type: .width)
}
.padding(.bottom, Padding.cellGap)
.sheet(isPresented: $isReportAProblemShown) {
WebView(url: reportAProblemLink)
WebView(url: viewModel.reportAProblemLink)
.ignoresSafeArea(edges: .bottom)
}
.sheet(isPresented: $isFullAboutShown) {
Expand Down Expand Up @@ -162,39 +185,6 @@ struct AboutView: View {
}
}

struct CompactActionItem: View {
let icon: String
let title: String
let accessibilityHint: String
let action: () -> Void

var body: some View {
Button(action: action) {
VStack(spacing: 8) {
Image(systemName: icon)
.font(.system(size: 24, weight: .medium))
.foregroundColor(.accentColor)
.frame(height: 32)

Text(title)
.font(.caption)
.multilineTextAlignment(.center)
.foregroundColor(.primary)
.lineLimit(2)
}
.frame(maxWidth: .infinity, minHeight: 80)
.padding(.vertical, 12)
.padding(.horizontal, 8)
.background(
Color.cellBackground,
in: RoundedRectangle(cornerRadius: Constants.cellRadius)
)
}
.buttonStyle(SquishyButtonStyle())
.accessibilityHint(accessibilityHint)
}
}

struct AboutView_Previews: PreviewProvider {
static var previews: some View {
AboutView()
Expand Down
Loading