Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
ec0f64c
Dashboard
petkybenedek Sep 26, 2025
142ba5a
Course details view (smart search excluded)
petkybenedek Oct 1, 2025
d2394de
Assignment list
petkybenedek Oct 10, 2025
2efbd63
Assignment details
petkybenedek Oct 10, 2025
c67bb52
Submission detail
petkybenedek Oct 10, 2025
62c9818
Discussion list
petkybenedek Oct 10, 2025
6c030e9
Correct spelling
petkybenedek Oct 14, 2025
65e1957
only ignore top
petkybenedek Oct 15, 2025
506af1e
Login
petkybenedek Oct 15, 2025
a25de76
Grade list
petkybenedek Oct 15, 2025
f7e0828
Grade list and filter
petkybenedek Oct 15, 2025
4fb0972
Remove comment
petkybenedek Oct 15, 2025
dfd55c9
People
petkybenedek Oct 15, 2025
94b63a9
Page list
petkybenedek Oct 15, 2025
e5cbb39
Pages
petkybenedek Oct 15, 2025
306c076
Files
petkybenedek Oct 16, 2025
dd1d972
Modules
petkybenedek Oct 16, 2025
2fbd7f5
quizzes
petkybenedek Oct 16, 2025
a28a463
Syllabus
petkybenedek Oct 16, 2025
38cd436
Conferences
petkybenedek Oct 16, 2025
3498eec
Inbox
petkybenedek Oct 20, 2025
7d041f0
Todo
petkybenedek Oct 20, 2025
88aec1a
Message details
petkybenedek Oct 20, 2025
0595d2b
WebViews
petkybenedek Oct 22, 2025
733fc6c
course details back button
petkybenedek Oct 22, 2025
97d332a
Merge branch 'master' into iOS26/Assignments-and-Discussions
petkybenedek Nov 14, 2025
1398bd7
Merge correction
petkybenedek Nov 14, 2025
13f56a1
Glassified bottom sheets in messages and dashboard
petkybenedek Nov 18, 2025
296fc5c
Glassifying Dashboard and file list
petkybenedek Nov 18, 2025
86e4c6b
Merge branch 'master' into chore/iOS-26-redesign
petkybenedek Nov 18, 2025
a9773a1
Smart search glassification
petkybenedek Nov 19, 2025
f40dcc6
Parent app
petkybenedek Nov 21, 2025
d8a3afd
Correct test
petkybenedek Nov 21, 2025
f53ae57
Correct tests
petkybenedek Nov 21, 2025
6bd7e39
Correct license header
petkybenedek Nov 21, 2025
ceb59f1
Correct test and center canvas logo
petkybenedek Nov 21, 2025
203d3a7
Add debug condition
petkybenedek Nov 21, 2025
cced7b1
Remove unecessary nav
petkybenedek Nov 21, 2025
9335aa3
Merge branch 'master' into chore/iOS-26-redesign
petkybenedek Nov 21, 2025
4a8bda7
Set ModuleItemSequenceViewController background
petkybenedek Nov 21, 2025
65560b7
Remove custom toolbar color from ModuleItemSequenceViewController
petkybenedek Nov 21, 2025
33eb7cc
K5, assignment details, grade list what-if score
petkybenedek Nov 24, 2025
fc6a5eb
Teacher assignment details
petkybenedek Nov 24, 2025
76e17eb
Correct discussion view controller test
petkybenedek Nov 24, 2025
c101401
Parent assignment details, teacher submission list
petkybenedek Nov 25, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,28 @@ public struct Brand: Equatable {
}
}

public func headerImageView() -> UIImageView {
let logoView = UIImageView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
logoView.contentMode = .scaleAspectFit
logoView.heightAnchor.constraint(equalToConstant: 44).isActive = true
logoView.widthAnchor.constraint(equalToConstant: 44).isActive = true
logoView.image = headerImage
logoView.backgroundColor = headerImageBackground
logoView.accessibilityElementsHidden = true
return logoView
}
@available(iOS, deprecated: 26, message: "Remove conditional code when iOS 18 support is dropped")
public func headerImageView() -> UIImageView {
if #available(iOS 26, *) {
let logoView = UIImageView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
logoView.contentMode = .scaleAspectFit
logoView.heightAnchor.constraint(equalToConstant: 44).isActive = true
logoView.widthAnchor.constraint(equalToConstant: 44).isActive = true
logoView.image = headerImage
logoView.backgroundColor = headerImageBackground
logoView.layer.cornerRadius = 8
logoView.clipsToBounds = true
logoView.accessibilityElementsHidden = true
return logoView
} else {
let logoView = UIImageView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
logoView.contentMode = .scaleAspectFit
logoView.heightAnchor.constraint(equalToConstant: 44).isActive = true
logoView.widthAnchor.constraint(equalToConstant: 44).isActive = true
logoView.image = headerImage
logoView.backgroundColor = headerImageBackground
logoView.accessibilityElementsHidden = true
return logoView
}
}
}
2 changes: 1 addition & 1 deletion Core/Core/Common/CommonModels/Router/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ open class Router {

if view is UIAlertController { return from.present(view, animated: true, completion: completion) }

if let displayModeButton = from.splitDisplayModeButtonItem,
if let displayModeButton = from.splitDisplayModeButtonItem, #unavailable(iOS 26),
from.splitViewController?.isCollapsed == false,
options.isDetail || from.isInSplitViewDetail,
!options.isModal {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,42 @@ public struct EmbeddedWebPageContainerScreen: View {
}

public var body: some View {
WebSession(url: viewModel.url) { sessionURL in
WebView(
url: sessionURL,
features: features,
canToggleTheme: true,
configuration: viewModel.webViewConfig
)
.onProvisionalNavigationStarted { webView, navigation in
viewModel.webView(webView, didStartProvisionalNavigation: navigation)
if #available(iOS 26, *) {
WebSession(url: viewModel.url) { sessionURL in
WebView(
url: sessionURL,
features: features,
canToggleTheme: true,
configuration: viewModel.webViewConfig
)
.onProvisionalNavigationStarted { webView, navigation in
viewModel.webView(webView, didStartProvisionalNavigation: navigation)
}
.navBarItems(leading: viewModel.leadingNavigationButton)
.onAppear {
viewModel.viewController = viewController.value
}
}
.navBarItems(leading: viewModel.leadingNavigationButton)
.onAppear {
viewModel.viewController = viewController.value
.navigationTitle(viewModel.navTitle)
.optionalNavigationSubtitle(viewModel.subTitle)
} else {
WebSession(url: viewModel.url) { sessionURL in
WebView(
url: sessionURL,
features: features,
canToggleTheme: true,
configuration: viewModel.webViewConfig
)
.onProvisionalNavigationStarted { webView, navigation in
viewModel.webView(webView, didStartProvisionalNavigation: navigation)
}
.navBarItems(leading: viewModel.leadingNavigationButton)
.onAppear {
viewModel.viewController = viewController.value
}
}
.navigationBarTitleView(title: viewModel.navTitle, subtitle: viewModel.subTitle)
.navigationBarStyle(.color(viewModel.contextColor))
}
.navigationBarTitleView(title: viewModel.navTitle, subtitle: viewModel.subTitle)
.navigationBarStyle(.color(viewModel.contextColor))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import SwiftUI

extension InstUI {

@available(iOS, deprecated: 26)
public struct NavigationBarTitleView: View {
@Environment(\.dynamicTypeSize) private var dynamicTypeSize
@Environment(\.navBarColors) private var navBarColors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@

import SwiftUI

@available(iOS, deprecated: 26)
protocol NavigationBarStyled: AnyObject {
var navigationBarStyle: NavigationBarStyle { get set }
}

@available(iOS, deprecated: 26)
struct NavigationBarStyleModifier: ViewModifier {
let style: NavigationBarStyle

Expand All @@ -47,6 +49,7 @@ struct RightBarButtonItemModifier: ViewModifier {
}
}

@available(iOS, deprecated: 26)
struct GlobalNavigationBarModifier: ViewModifier {
@Environment(\.viewController) var controller

Expand All @@ -56,6 +59,7 @@ struct GlobalNavigationBarModifier: ViewModifier {
}
}

@available(iOS, deprecated: 26)
struct NavBarBackButtonModifier: ViewModifier {
@Environment(\.viewController) private var controller

Expand All @@ -67,6 +71,26 @@ struct NavBarBackButtonModifier: ViewModifier {
}

extension View {
@available(iOS, introduced: 26)
@ViewBuilder
public func optionalNavigationSubtitle(_ subtitle: String?) -> some View {
if let subtitle {
self.navigationSubtitle(subtitle)
} else {
self
}
}

@available(iOS, introduced: 26)
@ViewBuilder
public func optionalNavigationTitle(_ title: String?) -> some View {
if let title {
self.navigationTitle(title)
} else {
self
}
}

/// Sets the navigation bar's background color, title color & font, button color & font.
/// - Warning: Make sure to call this method AFTER calling `navigationBarTitleView()` to affect it.
/// - Parameters:
Expand All @@ -75,6 +99,7 @@ extension View {
/// - `.modal` is primarily used on modal screens, but also on some screen which doesn't belong to a context, but not considered global.
/// - `.color()` is used on non-modal screens within a context (typically a course or group), and in some other cases.
/// - Use `.color(nil)` to keep the navigation bar's current context background color but ensure the proper title color is set.
@available(iOS, deprecated: 26)
public func navigationBarStyle(_ style: NavigationBarStyle) -> some View {
modifier(NavigationBarStyleModifier(style: style))
}
Expand All @@ -84,6 +109,7 @@ extension View {
/// - Parameters:
/// - title: The line is always displayed, even if this is empty. (This should not happen normally.)
/// - subtitle: The subtitle line is only displayed if this is not empty.
@available(iOS, deprecated: 26)
public func navigationBarTitleView(title: String, subtitle: String?) -> some View {
toolbar {
ToolbarItem(placement: .principal) {
Expand All @@ -94,12 +120,14 @@ extension View {

/// Sets the navigation bar's title, using the proper font. Please use this one instead of the native `navigationTitle()` method.
/// - Warning: Make sure to call `navigationBarStyle()` _**AFTER**_ this method to set the proper text color.
@available(iOS, deprecated: 26)
public func navigationBarTitleView(_ title: String) -> some View {
navigationBarTitleView(title: title, subtitle: nil)
}

/// Sets the navigation bar's background color, button color to match the `Brand.shared` colors,
/// sets the button font and sets the brand logo as the titleView.
@available(iOS, deprecated: 26)
public func navigationBarGlobal() -> some View {
modifier(GlobalNavigationBarModifier())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import UIKit

@available(iOS, deprecated: 26)
public protocol ColoredNavViewProtocol: AnyObject {
var color: UIColor? { get set }
var navigationController: UINavigationController? { get }
Expand All @@ -28,13 +29,19 @@ public protocol ColoredNavViewProtocol: AnyObject {
}

extension ColoredNavViewProtocol {
@available(iOS, deprecated: 26)
public func setupTitleViewInNavbar(title: String) {
guard #unavailable(iOS 26) else { return }

navigationItem.titleView = titleSubtitleView
titleSubtitleView.title = title
titleSubtitleView.accessibilityTraits = .header
}

@available(iOS, deprecated: 26)
public func updateNavBar(subtitle: String?, color: UIColor?) {
guard #unavailable(iOS 26) else { return }

self.color = color
titleSubtitleView.subtitle = subtitle
navigationController?.navigationBar.useContextColor(color)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import UIKit

@available(iOS, deprecated: 26)
public class TitleSubtitleView: UIView {
@IBOutlet public weak var titleLabel: UILabel!
@IBOutlet public weak var subtitleLabel: UILabel!
Expand Down Expand Up @@ -51,27 +52,37 @@ public class TitleSubtitleView: UIView {
}

public static func create() -> Self {
let view = loadFromXib()
view.titleLabel.text = ""
view.subtitleLabel.text = ""
view.titleLabel.font = .scaledNamedFont(.semibold16)
view.subtitleLabel.font = .scaledNamedFont(.regular14)
view.titleLabel.accessibilityElementsHidden = true
view.subtitleLabel.accessibilityElementsHidden = true
view.accessibilityTraits = [.header]
view.showsLargeContentViewer = true
view.addInteraction(UILargeContentViewerInteraction())
return view
let view = loadFromXib()

if #available(iOS 26, *) {
view.tintColor = .textDarkest
}

view.titleLabel.text = ""
view.subtitleLabel.text = ""
view.titleLabel.font = .scaledNamedFont(.semibold16)
view.subtitleLabel.font = .scaledNamedFont(.regular14)
view.titleLabel.accessibilityElementsHidden = true
view.subtitleLabel.accessibilityElementsHidden = true
view.accessibilityTraits = [.header]
view.showsLargeContentViewer = true
view.addInteraction(UILargeContentViewerInteraction())
return view
}

public func recreate() -> TitleSubtitleView {
let copy = TitleSubtitleView.create()

if #available(iOS 26, *) {
copy.tintColor = .textDarkest
}
copy.title = title
copy.subtitle = subtitle
return copy
}

public override func tintColorDidChange() {
guard #available(iOS 26, *) else { return }
let title = (superview?.superview as? UINavigationBar)?.titleTextAttributes?[.foregroundColor] as? UIColor
let color = title ?? tintColor
titleLabel.textColor = color
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ extension UINavigationBar {
}
}

@available(iOS, deprecated: 26)
public func useContextColor(_ color: UIColor?) {
guard let color else { return }
guard let color, #unavailable(iOS 26) else { return }
let foreground = UIColor.textLightest
let background = color
titleTextAttributes = [.foregroundColor: foreground]
Expand All @@ -45,7 +46,10 @@ extension UINavigationBar {
applyAppearanceChanges(backgroundColor: background, foregroundColor: foreground)
}

@available(iOS, deprecated: 26)
public func useGlobalNavStyle(brand: Brand = Brand.shared) {
guard #unavailable(iOS 26) else { return }

// TODO: Remove the isHorizon condition once horizon-specific logic is no longer needed.
let isHorizon = AppEnvironment.shared.app == .horizon
let background: UIColor = isHorizon ? .backgroundLightest : brand.navBackground
Expand Down
18 changes: 13 additions & 5 deletions Core/Core/Common/CommonUI/UIViews/CoreSplitViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public class CoreSplitViewController: UISplitViewController {
}
}

@available(iOS, deprecated: 26, message: "iOS26 has a default implementation")
public func prettyDisplayModeButtonItem(_ displayMode: DisplayMode) -> UIBarButtonItem {
let defaultButton = self.displayModeButtonItem
let collapse = displayMode == .oneOverSecondary || displayMode == .secondaryOnly
Expand All @@ -121,9 +122,13 @@ extension CoreSplitViewController: UISplitViewControllerDelegate {
public func splitViewController(_ svc: UISplitViewController, willChangeTo displayMode: UISplitViewController.DisplayMode) {
if svc.viewControllers.count == 2 {
let top = (svc.viewControllers.last as? UINavigationController)?.topViewController
top?.navigationItem.leftItemsSupplementBackButton = true
if #unavailable(iOS 26) {
top?.navigationItem.leftItemsSupplementBackButton = true
}
if top?.isKind(of: EmptyViewController.self) == false {
top?.navigationItem.leftBarButtonItem = prettyDisplayModeButtonItem(displayMode)
if #unavailable(iOS 26) {
top?.navigationItem.leftBarButtonItem = prettyDisplayModeButtonItem(displayMode)
}
NotificationCenter.default.post(name: NSNotification.Name.SplitViewControllerWillChangeDisplayModeNotification, object: self)
}
}
Expand Down Expand Up @@ -179,9 +184,12 @@ extension CoreSplitViewController: UISplitViewControllerDelegate {
}

let viewControllers = (newDeets as? UINavigationController)?.viewControllers ?? [newDeets]
for vc in viewControllers {
vc.navigationItem.leftItemsSupplementBackButton = true
vc.navigationItem.leftBarButtonItem = prettyDisplayModeButtonItem(splitViewController.displayMode)

if #unavailable(iOS 26) {
for vc in viewControllers {
vc.navigationItem.leftItemsSupplementBackButton = true
vc.navigationItem.leftBarButtonItem = prettyDisplayModeButtonItem(splitViewController.displayMode)
}
}

if let nav = newDeets as? UINavigationController {
Expand Down
6 changes: 3 additions & 3 deletions Core/Core/Common/CommonUI/UIViews/EmptyViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ public class EmptyViewController: UIViewController {
logoImageView.tintColor = .textDark
logoImageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
logoImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
logoImageView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
logoImageView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.1),
logoImageView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
logoImageView.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor),
logoImageView.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor, multiplier: 0.2),
logoImageView.heightAnchor.constraint(equalTo: logoImageView.widthAnchor)
])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ open class HorizontalMenuViewController: ScreenViewTrackerViewController {
public weak var delegate: HorizontalPagedMenuDelegate?
public private(set) var selectedIndexPath: IndexPath = IndexPath(item: 0, section: 0)

private var itemCount: Int {
public var itemCount: Int {
return delegate?.numberOfMenuItems ?? 0
}

Expand Down Expand Up @@ -78,8 +78,16 @@ open class HorizontalMenuViewController: ScreenViewTrackerViewController {
} else {
setupMenu()
setupPages()
setupUnderline()
setupBottomBorder()

// Only show the underline on iOS 26 if there are more than one tabs
if #available(iOS 26, *) {
if itemCount > 1 {
setupUnderline()
}
} else {
setupUnderline()
}
}
}

Expand Down
Loading