Skip to content

Commit 0c00137

Browse files
committed
Merging in from feature/horizon
2 parents b0d99cf + fd7480a commit 0c00137

File tree

272 files changed

+9335
-3593
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

272 files changed

+9335
-3593
lines changed

.swiftlint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ included: # paths to include during linting. `--path` is ignored if present.
2020
- Horizon
2121
- Parent
2222
- TestsFoundation
23+
- packages/HorizonUI/Sources/HorizonUI
2324
- scripts/swift
2425
excluded: # paths to ignore during linting. Takes precedence over `included`.
2526

Canvas.xcworkspace/contents.xcworkspacedata

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Canvas.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// This file is part of Canvas.
3+
// Copyright (C) 2025-present Instructure, Inc.
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as
7+
// published by the Free Software Foundation, either version 3 of the
8+
// License, or (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
//
18+
19+
public protocol DebugDescriptionProvider {
20+
/// The non-localized string representation of an entity for debugging / analytics purposes.
21+
var debugDescription: String { get }
22+
}

Core/Core/Common/CommonModels/AppEnvironment/AppEnvironmentOverride.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ extension AppEnvironment {
112112

113113
return .shared
114114
}
115+
116+
/// This method returns an `AppEnvironmentOverride` using the given `baseURL`s host if it
117+
/// doesn't match the one on `AppEnvironment.shared`.
118+
static func resolved(for baseURL: URL?) -> AppEnvironment {
119+
guard
120+
let baseURL,
121+
let components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false)
122+
else { return .shared }
123+
return resolved(for: components)
124+
}
115125
}
116126

117127
// MARK: - Utils

Core/Core/Common/CommonModels/AppEnvironment/SessionDefaults.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,6 @@ public struct SessionDefaults: Equatable {
230230
}
231231

232232
// MARK: - Grades
233-
public var selectedGradingPeriodIdsByCourseIDs: [String: String]? {
234-
get { self["selectedGradingPeriodIdsByCourseIDs"] as? [String: String] }
235-
set { self["selectedGradingPeriodIdsByCourseIDs"] = newValue }
236-
}
237-
238233
public var selectedSortByOptionIDs: [String: String]? {
239234
get { self["selectedSortByOptionIDs"] as? [String: String] }
240235
set { self["selectedSortByOptionIDs"] = newValue }

Core/Core/Common/CommonModels/Router/DefaultViewProvider.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,23 @@ import UIKit
2424
View controllers implementing this protocol can provide a default view for such situations.
2525
*/
2626
public protocol DefaultViewProvider: UIViewController {
27-
var defaultViewRoute: DefaultViewRouteParameters? { get set }
27+
var defaultViewRoute: DefaultViewRouteParameters? { get }
28+
func setDefaultViewRoute(_ route: DefaultViewRouteParameters?)
2829
}
2930

30-
public struct DefaultViewRouteParameters {
31+
public struct DefaultViewRouteParameters: ExpressibleByStringLiteral {
3132
let url: String
3233
let userInfo: [String: Any]?
3334

3435
public init(url: String, userInfo: [String: Any]? = nil) {
3536
self.url = url
3637
self.userInfo = userInfo
3738
}
39+
40+
public init(stringLiteral value: StringLiteralType) {
41+
self.url = value
42+
self.userInfo = nil
43+
}
3844
}
3945

4046
extension UIViewController {

Core/Core/Common/CommonModels/Router/Router.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,11 @@ open class Router {
180180
#endif
181181

182182
// block disabled course tab urls
183-
if let courseTabUrlInteractor, let url = url.url, !courseTabUrlInteractor.isAllowedUrl(url, userInfo: userInfo) {
183+
if env.app == .student,
184+
let courseTabUrlInteractor,
185+
let url = url.url,
186+
!courseTabUrlInteractor.isAllowedUrl(url, userInfo: userInfo) {
187+
184188
let snackBarViewModel = from.findSnackBarViewModel()
185189
snackBarViewModel?.showSnack(
186190
String(localized: "That page has been disabled for this course.", bundle: .core),

Core/Core/Common/CommonUI/CoreWebView/View/CoreWebView.swift

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ open class CoreWebView: WKWebView {
166166
guard let src = message.body as? String else { return }
167167
self?.loadFrame(src: src)
168168
}
169+
170+
registerForTraitChanges()
169171
}
170172

171173
@discardableResult
@@ -363,6 +365,18 @@ open class CoreWebView: WKWebView {
363365
fileLoadCompletion?(.init(error: error))
364366
}
365367
}
368+
369+
private func registerForTraitChanges() {
370+
let traits = [UITraitUserInterfaceStyle.self]
371+
registerForTraitChanges(traits) { (self: CoreWebView, _) in
372+
self.updateInterfaceStyle()
373+
}
374+
}
375+
376+
func updateInterfaceStyle() {
377+
let traitCollection = viewController?.traitCollection ?? traitCollection
378+
themeSwitcher?.updateUserInterfaceStyle(with: traitCollection.userInterfaceStyle)
379+
}
366380
}
367381

368382
// MARK: - WKNavigationDelegate
@@ -409,7 +423,7 @@ extension CoreWebView: WKNavigationDelegate {
409423
// involved (like Zoom and Microsoft).
410424
// When there's additional JavaScript code behind an LTI Button (like DBQ Online), we don't want to
411425
// handle those cases here, because `createWebViewWith` already opened a new popup window.
412-
if let tools = LTITools(link: action.request.url, navigationType: action.navigationType),
426+
if let tools = LTITools(link: action.request.url, navigationType: action.navigationType, env: env),
413427
let from = linkDelegate?.routeLinksFrom {
414428
tools.presentTool(from: from, animated: true)
415429
return decisionHandler(.cancel)
@@ -704,14 +718,6 @@ extension CoreWebView {
704718
themeSwitcher?.updateUserInterfaceStyle(with: .current)
705719
activateFullScreenSupport()
706720
}
707-
708-
public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
709-
super.traitCollectionDidChange(previousTraitCollection)
710-
let traitCollection = viewController?.traitCollection ?? traitCollection
711-
guard previousTraitCollection?.userInterfaceStyle != traitCollection.userInterfaceStyle else { return }
712-
713-
themeSwitcher?.updateUserInterfaceStyle(with: traitCollection.userInterfaceStyle)
714-
}
715721
}
716722

717723
// MARK: Offline parsing

Core/Core/Common/CommonUI/CoreWebView/View/CoreWebViewThemeSwitcher.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,12 @@ final class CoreWebViewThemeSwitcherLive: CoreWebViewThemeSwitcher {
145145
private func updateOverrideUserInterfaceStyle() {
146146
let currentStyle: UIUserInterfaceStyle = isThemeDark ? (isInverted ? .light : .dark) : .light
147147

148-
// When `overrideUserInterfaceStyle != .unspecified` the `traitCollectionDidChange()` method is not called,
149-
// so we need to observe it from the outside. This problem may go away once minimum deployment target is set to iOS17.
148+
/// Though we are registered to user interface changes In CoreWebView and updateUserInterfaceStyle should be triggered
149+
/// on trait changes, but it's not happening when overrideUserInterfaceStyle is not unspecified, so we still need this workaround.
150+
/// Latest check was with iOS 18.4.
150151
if host?.overrideUserInterfaceStyle == .unspecified && currentStyle != .unspecified {
151152
addUserInterfaceStyleDidChangeObserver()
152153
}
153-
154154
// override style, based on current settings
155155
host?.overrideUserInterfaceStyle = currentStyle
156156

0 commit comments

Comments
 (0)