Skip to content

Commit 4e2b6e8

Browse files
committed
feat: 1.5.1
1 parent b261561 commit 4e2b6e8

File tree

11 files changed

+469
-202
lines changed

11 files changed

+469
-202
lines changed

Fosdem.xcodeproj/project.pbxproj

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
920085662D42F2D70082719F /* ListStatusOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920085652D42F2D70082719F /* ListStatusOverlay.swift */; };
2525
9203845F2B5B0A2100B793AA /* PentabarfKit in Frameworks */ = {isa = PBXBuildFile; productRef = 9203845E2B5B0A2100B793AA /* PentabarfKit */; };
2626
9221BD832D60CFDD00E0046E /* SectionedQuery in Frameworks */ = {isa = PBXBuildFile; productRef = 9221BD822D60CFDD00E0046E /* SectionedQuery */; };
27+
923E22542F1D131D0094B2DC /* EventContainingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923E22532F1D13180094B2DC /* EventContainingModel.swift */; };
2728
924E15BC2922C637005A8EA2 /* RoomStatusImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924E15BB2922C637005A8EA2 /* RoomStatusImporter.swift */; };
2829
924E15BE2922CCA9005A8EA2 /* RoomState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924E15BD2922CCA9005A8EA2 /* RoomState.swift */; };
2930
924E15C329238AA5005A8EA2 /* EventListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924E15C229238AA5005A8EA2 /* EventListItem.swift */; };
@@ -51,6 +52,7 @@
5152
92D9E7B8291D7B9B007D203D /* HTMLFormattedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D9E7B7291D7B9B007D203D /* HTMLFormattedText.swift */; };
5253
92E5C1152D4820A60017CEE0 /* ListPredicateType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92E5C1142D4820A60017CEE0 /* ListPredicateType.swift */; };
5354
92F70AA02922B49A000BE6CB /* UrlHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92F70A9F2922B49A000BE6CB /* UrlHelper.swift */; };
55+
92FB7C582F16D890008352FB /* TimelineUI in Frameworks */ = {isa = PBXBuildFile; productRef = 92FB7C572F16D890008352FB /* TimelineUI */; };
5456
/* End PBXBuildFile section */
5557

5658
/* Begin PBXContainerItemProxy section */
@@ -92,6 +94,7 @@
9294
14D2773F2205D07500740042 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9395
14D2774B2205D19D00740042 /* RemoteScheduleFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteScheduleFetcher.swift; sourceTree = "<group>"; };
9496
920085652D42F2D70082719F /* ListStatusOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStatusOverlay.swift; sourceTree = "<group>"; };
97+
923E22532F1D13180094B2DC /* EventContainingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventContainingModel.swift; sourceTree = "<group>"; };
9598
924E15BB2922C637005A8EA2 /* RoomStatusImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStatusImporter.swift; sourceTree = "<group>"; };
9699
924E15BD2922CCA9005A8EA2 /* RoomState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomState.swift; sourceTree = "<group>"; };
97100
924E15C229238AA5005A8EA2 /* EventListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventListItem.swift; sourceTree = "<group>"; };
@@ -137,6 +140,7 @@
137140
isa = PBXFrameworksBuildPhase;
138141
buildActionMask = 2147483647;
139142
files = (
143+
92FB7C582F16D890008352FB /* TimelineUI in Frameworks */,
140144
9221BD832D60CFDD00E0046E /* SectionedQuery in Frameworks */,
141145
9203845F2B5B0A2100B793AA /* PentabarfKit in Frameworks */,
142146
);
@@ -172,6 +176,7 @@
172176
146A86632205E159008A61AD /* Models */ = {
173177
isa = PBXGroup;
174178
children = (
179+
923E22532F1D13180094B2DC /* EventContainingModel.swift */,
175180
146A86782206ED84008A61AD /* Track.swift */,
176181
142A87432224752E0034F6D7 /* EventType.swift */,
177182
146A867D22089497008A61AD /* Link.swift */,
@@ -208,6 +213,7 @@
208213
14D277172205D07200740042 /* Fosdem */,
209214
14D277312205D07500740042 /* FosdemTests */,
210215
14D2773C2205D07500740042 /* FosdemUITests */,
216+
92FB7C562F16D890008352FB /* Frameworks */,
211217
14D277162205D07200740042 /* Products */,
212218
);
213219
sourceTree = "<group>";
@@ -297,6 +303,13 @@
297303
path = Utils;
298304
sourceTree = "<group>";
299305
};
306+
92FB7C562F16D890008352FB /* Frameworks */ = {
307+
isa = PBXGroup;
308+
children = (
309+
);
310+
name = Frameworks;
311+
sourceTree = "<group>";
312+
};
300313
/* End PBXGroup section */
301314

302315
/* Begin PBXNativeTarget section */
@@ -321,6 +334,7 @@
321334
packageProductDependencies = (
322335
9203845E2B5B0A2100B793AA /* PentabarfKit */,
323336
9221BD822D60CFDD00E0046E /* SectionedQuery */,
337+
92FB7C572F16D890008352FB /* TimelineUI */,
324338
);
325339
productName = Fosdem;
326340
productReference = 14D277152205D07200740042 /* Fosdem.app */;
@@ -402,6 +416,7 @@
402416
packageReferences = (
403417
9203845D2B5B0A2100B793AA /* XCRemoteSwiftPackageReference "PentabarfKit" */,
404418
9221BD812D60CFDD00E0046E /* XCRemoteSwiftPackageReference "swiftdata-sectionedquery" */,
419+
92FB7C552F16D7EB008352FB /* XCRemoteSwiftPackageReference "timeline-ui" */,
405420
);
406421
preferredProjectObjectVersion = 77;
407422
productRefGroup = 14D277162205D07200740042 /* Products */;
@@ -480,6 +495,7 @@
480495
142A8742222473A40034F6D7 /* UIColor+hexstring.swift in Sources */,
481496
92CE31AF28FC49DC0073813E /* SettingsHelper.swift in Sources */,
482497
9268D79A298F251E0067A6B1 /* ListSettings.swift in Sources */,
498+
923E22542F1D131D0094B2DC /* EventContainingModel.swift in Sources */,
483499
92C271D02922292500E8C25D /* PreviewEvent.swift in Sources */,
484500
925B0263298EB2A400AFA83D /* VideoPlayer.swift in Sources */,
485501
146A867E22089497008A61AD /* Link.swift in Sources */,
@@ -696,7 +712,7 @@
696712
"@executable_path/Frameworks",
697713
);
698714
MACOSX_DEPLOYMENT_TARGET = 26.1;
699-
MARKETING_VERSION = 1.5.0;
715+
MARKETING_VERSION = 1.5.1;
700716
PRODUCT_BUNDLE_IDENTIFIER = eu.seanmolenaar.Fosdem;
701717
PRODUCT_NAME = "$(TARGET_NAME)";
702718
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -725,7 +741,7 @@
725741
"@executable_path/Frameworks",
726742
);
727743
MACOSX_DEPLOYMENT_TARGET = 26.1;
728-
MARKETING_VERSION = 1.5.0;
744+
MARKETING_VERSION = 1.5.1;
729745
PRODUCT_BUNDLE_IDENTIFIER = eu.seanmolenaar.Fosdem;
730746
PRODUCT_NAME = "$(TARGET_NAME)";
731747
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -880,6 +896,14 @@
880896
minimumVersion = 1.0.3;
881897
};
882898
};
899+
92FB7C552F16D7EB008352FB /* XCRemoteSwiftPackageReference "timeline-ui" */ = {
900+
isa = XCRemoteSwiftPackageReference;
901+
repositoryURL = "https://codeberg.org/ctietze/timeline-ui.git";
902+
requirement = {
903+
kind = upToNextMajorVersion;
904+
minimumVersion = 1.1.0;
905+
};
906+
};
883907
/* End XCRemoteSwiftPackageReference section */
884908

885909
/* Begin XCSwiftPackageProductDependency section */
@@ -893,6 +917,11 @@
893917
package = 9221BD812D60CFDD00E0046E /* XCRemoteSwiftPackageReference "swiftdata-sectionedquery" */;
894918
productName = SectionedQuery;
895919
};
920+
92FB7C572F16D890008352FB /* TimelineUI */ = {
921+
isa = XCSwiftPackageProductDependency;
922+
package = 92FB7C552F16D7EB008352FB /* XCRemoteSwiftPackageReference "timeline-ui" */;
923+
productName = TimelineUI;
924+
};
896925
92FC93092B5C2DA100C2D13D /* PentabarfKit */ = {
897926
isa = XCSwiftPackageProductDependency;
898927
package = 9203845D2B5B0A2100B793AA /* XCRemoteSwiftPackageReference "PentabarfKit" */;

Fosdem/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<key>CFBundlePackageType</key>
1616
<string>APPL</string>
1717
<key>CFBundleShortVersionString</key>
18-
<string>1.5.0</string>
18+
<string>1.5.1</string>
1919
<key>CFBundleVersion</key>
2020
<string>1</string>
2121
<key>ITSAppUsesNonExemptEncryption</key>

Fosdem/ListPredicateType.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,30 @@ enum ListPredicateType {
1717
return [.track, .room]
1818
}
1919

20+
static func fromType(_ type: any EventContainingModel.Type) -> ListPredicateType? {
21+
switch type {
22+
case is Room.Type:
23+
return .room
24+
case is Track.Type:
25+
return .track
26+
case is Person.Type:
27+
return .person
28+
default:
29+
return nil
30+
}
31+
}
32+
33+
public func asType(_ type: ListPredicateType) -> any EventContainingModel.Type {
34+
switch type {
35+
case .person:
36+
return Person.self
37+
case .room:
38+
return Room.self
39+
case .track:
40+
return Track.self
41+
}
42+
}
43+
2044
static func getName(_ type: ListPredicateType) -> String {
2145
switch type {
2246
case .person:

Fosdem/Models/Event.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class Event {
4242
public var roomName: String { return room.name }
4343

4444
@Transient
45-
public var typeName: String { return type.name }
45+
public var typeName: String { return type!.name }
4646

4747
@Transient
4848
var year: String { return startInFormat("yyyy") }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// EventContainingModel.swift
3+
// Fosdem
4+
//
5+
// Created by Sean Molenaar on 18/01/2026.
6+
// Copyright © 2026 Sean Molenaar. All rights reserved.
7+
//
8+
import SwiftData
9+
10+
public protocol EventContainingModel: PersistentModel {
11+
var events: [Event] { get set }
12+
}
13+
14+
extension Track: EventContainingModel {}
15+
16+
extension Room: EventContainingModel {}
17+
18+
extension Person: EventContainingModel {}

Fosdem/Utils/ListSettings.swift

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,41 +12,87 @@ import SwiftUI
1212
class ListSettings: ObservableObject {
1313
@Published var onlyFuture: Bool = false
1414
@Published var deniedTypes: [String] = []
15+
@Published var deniedRooms: [String] = []
16+
@Published var deniedTracks: [String] = []
1517

1618
var isFiltering: Bool {
1719
onlyFuture || !deniedTypes.isEmpty
1820
}
1921

20-
public func predicate(_ type: ListPredicateType) -> Predicate<Event>? {
21-
var predicate: Predicate<Event>?
22+
@available(*, deprecated, renamed: "eventPredicate", message: "Should use more specific predicate")
23+
public func predicate(_ type: ListPredicateType) -> Predicate<Event> {
24+
return self.eventPredicate()
25+
}
2226

23-
if type == .person {
24-
let basePredicate = #Predicate<Event> { !$0.authors.isEmpty }
25-
if predicate != nil {
26-
predicate = #Predicate<Event> { predicate!.evaluate($0) && basePredicate.evaluate($0) }
27-
} else {
28-
predicate = basePredicate
29-
}
30-
}
27+
public func eventPredicate() -> Predicate<Event> {
28+
var predicate: Predicate<Event> = #Predicate<Event> { _ in true }
3129

3230
if onlyFuture {
3331
let basePredicate = ListSettings.futurePredicate()
34-
if predicate != nil {
35-
predicate = #Predicate<Event> { predicate!.evaluate($0) && basePredicate.evaluate($0) }
36-
} else {
37-
predicate = basePredicate
38-
}
32+
predicate = #Predicate<Event> { predicate.evaluate($0) && basePredicate.evaluate($0) }
3933
}
4034

4135
if !deniedTypes.isEmpty {
4236
let basePredicate = #Predicate<Event> {
4337
!deniedTypes.contains($0.typeName)
4438
}
45-
if predicate != nil {
46-
predicate = #Predicate<Event> { predicate!.evaluate($0) && basePredicate.evaluate($0) }
47-
} else {
48-
predicate = basePredicate
39+
predicate = #Predicate<Event> { predicate.evaluate($0) && basePredicate.evaluate($0) }
40+
}
41+
42+
return predicate
43+
}
44+
45+
public func roomPredicate() -> Predicate<Room> {
46+
var predicate: Predicate<Room> = #Predicate<Room> { _ in true }
47+
48+
if onlyFuture {
49+
let now = Date()
50+
let basePredicate = #Predicate<Room> { room in
51+
room.events.allSatisfy({ $0.end > now })
52+
}
53+
predicate = #Predicate<Room> { predicate.evaluate($0) && basePredicate.evaluate($0) }
54+
}
55+
56+
if !deniedTypes.isEmpty {
57+
let basePredicate = #Predicate<Room> { room in
58+
room.events.allSatisfy { !deniedTypes.contains($0.typeName) }
59+
}
60+
predicate = #Predicate<Room> { predicate.evaluate($0) && basePredicate.evaluate($0) }
61+
}
62+
63+
if !deniedRooms.isEmpty {
64+
let basePredicate = #Predicate<Room> { room in
65+
!deniedRooms.contains(room.name)
66+
}
67+
predicate = #Predicate<Room> { predicate.evaluate($0) && basePredicate.evaluate($0) }
68+
}
69+
70+
return predicate
71+
}
72+
73+
public func trackPredicate() -> Predicate<Track> {
74+
var predicate: Predicate<Track> = #Predicate<Track> { _ in true }
75+
76+
if onlyFuture {
77+
let now = Date()
78+
let basePredicate = #Predicate<Track> { track in
79+
track.events.allSatisfy({ $0.end > now })
80+
}
81+
predicate = #Predicate<Track> { predicate.evaluate($0) && basePredicate.evaluate($0) }
82+
}
83+
84+
if !deniedTypes.isEmpty {
85+
let basePredicate = #Predicate<Track> { track in
86+
track.events.allSatisfy { !deniedTypes.contains($0.typeName) }
87+
}
88+
predicate = #Predicate<Track> { predicate.evaluate($0) && basePredicate.evaluate($0) }
89+
}
90+
91+
if !deniedTracks.isEmpty {
92+
let basePredicate = #Predicate<Track> { track in
93+
!deniedTracks.contains(track.name)
4994
}
95+
predicate = #Predicate<Track> { predicate.evaluate($0) && basePredicate.evaluate($0) }
5096
}
5197

5298
return predicate

0 commit comments

Comments
 (0)