Skip to content

Commit 830ff28

Browse files
authored
[MBL-19448][S] To-do - Improvements (#3781)
refs: MBL-19448 builds: Student affects: Student release note: none
1 parent adf5ff8 commit 830ff28

37 files changed

+530
-400
lines changed

Core/Core/Common/CommonModels/Store/UseCase.swift

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -170,25 +170,26 @@ public extension UseCase {
170170
performUIUpdate {
171171
completion(.failure(error))
172172
}
173-
} else {
174-
environment.database.performWriteTask { context in
175-
do {
176-
self.reset(context: context)
177-
self.write(response: response, urlResponse: urlResponse, to: context)
178-
self.updateTTL(in: context)
179-
try context.save()
180-
performUIUpdate {
181-
completion(.success((response, urlResponse)))
182-
}
183-
} catch let dbError {
184-
Logger.shared.error(dbError.localizedDescription)
185-
RemoteLogger.shared.logError(
186-
name: "CoreData save failed",
187-
reason: dbError.localizedDescription
188-
)
189-
performUIUpdate {
190-
completion(.failure(dbError))
191-
}
173+
return
174+
}
175+
176+
environment.database.performWriteTask { context in
177+
do {
178+
self.reset(context: context)
179+
self.write(response: response, urlResponse: urlResponse, to: context)
180+
self.updateTTL(in: context)
181+
try context.save()
182+
performUIUpdate {
183+
completion(.success((response, urlResponse)))
184+
}
185+
} catch let dbError {
186+
Logger.shared.error(dbError.localizedDescription)
187+
RemoteLogger.shared.logError(
188+
name: "CoreData save failed",
189+
reason: dbError.localizedDescription
190+
)
191+
performUIUpdate {
192+
completion(.failure(dbError))
192193
}
193194
}
194195
}

Core/Core/Common/CommonUI/InstUI/Utils/SwipeAction.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,14 @@ extension View {
3838
/// - Parameters:
3939
/// - backgroundColor: The background color revealed behind the content during the swipe.
4040
/// - completionBehavior: Determines what happens after the swipe action completes. Defaults to `.stayOpen`.
41-
/// - isSwiping: Binding that tracks whether a swipe gesture is currently active. Use this to disable scrolling or other gestures while swiping.
41+
/// - isSwiping: Binding that tracks whether a swipe gesture is currently active.
42+
/// Use this to disable scrolling or other gestures while swiping.
4243
/// - isEnabled: Whether the swipe gesture is enabled. Defaults to `true`.
43-
/// - onSwipeCommitted: Optional closure called immediately when the swipe action is committed (user releases after reaching threshold) but before animations finish.
44-
/// - onSwipe: Closure called when the swipe action is completed animations included. For `.reset` behavior, this is called after the close animation finishes. For `.stayOpen` behavior, this is called while the open animation is running.
44+
/// - onSwipeCommitted: Optional closure called immediately when the swipe action is committed
45+
/// (user releases after reaching threshold) but before animations finish.
46+
/// - onSwipe: Closure called when the swipe action is completed animations included.
47+
/// For `.reset` behavior, this is called after the close animation finishes.
48+
/// For `.stayOpen` behavior, this is called while the open animation is running.
4549
/// - label: The view displayed in the revealed area during the swipe.
4650
public func swipeAction<Label: View>(
4751
backgroundColor: Color,

Core/Core/Common/Extensions/Foundation/DateExtensions.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,15 @@ public extension Date {
192192
return formatter
193193
}()
194194

195+
/**
196+
This date formatter displays abbreviated month names. E.g.: Jan, Feb, Mar.
197+
*/
198+
private static var monthFormatterAbbreviated: DateFormatter = {
199+
let formatter = DateFormatter()
200+
formatter.setLocalizedDateFormatFromTemplate("MMM")
201+
return formatter
202+
}()
203+
195204
/**
196205
This date formatter displays the full month name and the day of the month. E.g.: September 6.
197206
*/
@@ -304,6 +313,13 @@ public extension Date {
304313
Date.weekdayFormatterAbbreviated.string(from: self)
305314
}
306315

316+
/**
317+
E.g.: Jan, Feb, Mar
318+
*/
319+
var monthNameAbbreviated: String {
320+
Date.monthFormatterAbbreviated.string(from: self)
321+
}
322+
307323
/**
308324
E.g.: September 6.
309325
*/

Core/Core/Common/Extensions/Foundation/NotificationCenterExtensions.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extension NSNotification.Name {
2626
public static let showGradesOnDashboardDidChange = Notification.Name("com.instructure.core.notification.showGradesOnDashboardDidChange")
2727
public static let favoritesDidChange = Notification.Name("course-favorite-change")
2828
public static let windowUserInterfaceStyleDidChange = Notification.Name("com.instructure.core.notification.windowUserInterfaceStyleDidChange")
29+
public static let plannerItemDidChange = Notification.Name("com.instructure.core.notification.plannerItemDidChange")
2930
}
3031

3132
extension NotificationCenter {

Core/Core/Features/Courses/GetCourses.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public class GetCourse: APIUseCase {
6868
}
6969
}
7070

71-
public class GetCourses: CollectionUseCase {
71+
public class GetCourses: APIUseCase {
7272
public typealias Model = Course
7373
public typealias Response = GetCoursesRequest.Response
7474

@@ -108,6 +108,27 @@ public class GetCourses: CollectionUseCase {
108108
self.enrollmentState = enrollmentState
109109
self.perPage = perPage
110110
}
111+
112+
public func write(response: GetCoursesRequest.Response?, urlResponse _: URLResponse?, to client: NSManagedObjectContext) {
113+
guard let response else { return }
114+
115+
Self.deleteCoursesNotInResponse(response, scope: scope, in: client)
116+
117+
response.forEach {
118+
Course.save($0, in: client)
119+
}
120+
}
121+
122+
public static func deleteCoursesNotInResponse(
123+
_ response: [APICourse],
124+
scope: Scope,
125+
in context: NSManagedObjectContext
126+
) {
127+
let idsToKeep = Set(response.map { $0.id.value })
128+
let existingCourses: [Course] = context.fetch(scope: scope)
129+
let coursesToDelete = existingCourses.filter { !idsToKeep.contains($0.id) }
130+
context.delete(coursesToDelete)
131+
}
111132
}
112133

113134
public class GetAllCourses: CollectionUseCase {

Core/Core/Features/Dashboard/CourseCardList/Model/UseCase/GetDashboardCourses.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import CoreData
2020
import Foundation
2121

22-
public class GetDashboardCourses: CollectionUseCase {
22+
public class GetDashboardCourses: APIUseCase {
2323
public typealias Model = Course
2424

2525
public var cacheKey: String? { "get-dashboard-courses-\(enrollmentState)" }
@@ -45,11 +45,11 @@ public class GetDashboardCourses: CollectionUseCase {
4545

4646
public func write(response: [APICourse]?, urlResponse _: URLResponse?, to client: NSManagedObjectContext) {
4747
guard let response else { return }
48+
49+
GetCourses.deleteCoursesNotInResponse(response, scope: scope, in: client)
50+
4851
response.forEach {
49-
Course.save(
50-
$0,
51-
in: client
52-
)
52+
Course.save($0, in: client)
5353
}
5454
}
5555
}

Core/Core/Features/Planner/CalendarEvent/Model/UseCase/CreateCalendarEvent.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@ final class CreateCalendarEvent: APIUseCase {
5959
guard let response else { return }
6060

6161
CalendarEvent.save(response, in: client)
62+
NotificationCenter.default.post(name: .plannerItemDidChange, object: nil)
6263
}
6364
}

Core/Core/Features/Planner/CalendarEvent/Model/UseCase/DeleteCalendarEvent.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,9 @@ final class DeleteCalendarEvent: DeleteUseCase {
3939
body: .init(which: seriesModificationType)
4040
)
4141
}
42+
43+
func write(response: Response?, urlResponse: URLResponse?, to client: NSManagedObjectContext) {
44+
client.delete(client.fetch(scope: scope) as [Model])
45+
NotificationCenter.default.post(name: .plannerItemDidChange, object: nil)
46+
}
4247
}

Core/Core/Features/Planner/CalendarEvent/Model/UseCase/UpdateCalendarEvent.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,6 @@ final class UpdateCalendarEvent: APIUseCase {
6363
guard let response else { return }
6464

6565
CalendarEvent.save(response, in: client)
66+
NotificationCenter.default.post(name: .plannerItemDidChange, object: nil)
6667
}
6768
}

Core/Core/Features/Planner/CalendarToDo/Model/UseCase/CreatePlannerNote.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,6 @@ final class CreatePlannerNote: APIUseCase {
5454
guard let response else { return }
5555

5656
Plannable.save(response, contextName: courseName, in: client)
57+
NotificationCenter.default.post(name: .plannerItemDidChange, object: nil)
5758
}
5859
}

0 commit comments

Comments
 (0)