|
|
@@ -5654,11 +5654,10 @@ private final class EnrolledClassDetailsViewController: NSViewController {
|
|
5654
|
5654
|
container.addArrangedSubview(makeAttachmentPreview(item.attachments[0]))
|
|
5655
|
5655
|
}
|
|
5656
|
5656
|
if let link = item.alternateLink {
|
|
5657
|
|
- let open = makeInlineActionButton(title: "Open announcement", url: link)
|
|
|
5657
|
+ let open = makeStreamFooterActionButton(title: "Open announcement", systemSymbol: "arrow.up.right.square", url: link)
|
|
5658
|
5658
|
container.addArrangedSubview(open)
|
|
5659
|
5659
|
}
|
|
5660
|
|
- container.addArrangedSubview(makeCommentRow())
|
|
5661
|
|
- return wrapInStreamCard(container)
|
|
|
5660
|
+ return wrapInStreamCard(container, url: item.alternateLink)
|
|
5662
|
5661
|
}
|
|
5663
|
5662
|
|
|
5664
|
5663
|
private func makeCourseworkCard(_ item: ClassroomCourseWork) -> NSView {
|
|
|
@@ -5675,10 +5674,10 @@ private final class EnrolledClassDetailsViewController: NSViewController {
|
|
5675
|
5674
|
container.addArrangedSubview(makeAttachmentPreview(item.attachments[0]))
|
|
5676
|
5675
|
}
|
|
5677
|
5676
|
if let link = item.alternateLink {
|
|
5678
|
|
- let open = makeInlineActionButton(title: "Open item", url: link)
|
|
|
5677
|
+ let open = makeStreamFooterActionButton(title: "Open item", systemSymbol: "arrow.up.right.square", url: link)
|
|
5679
|
5678
|
container.addArrangedSubview(open)
|
|
5680
|
5679
|
}
|
|
5681
|
|
- return wrapInStreamCard(container)
|
|
|
5680
|
+ return wrapInStreamCard(container, url: item.alternateLink)
|
|
5682
|
5681
|
}
|
|
5683
|
5682
|
|
|
5684
|
5683
|
private func makeAttachmentsList(_ attachments: [ClassroomAttachment]) -> NSView {
|
|
|
@@ -5747,32 +5746,40 @@ private final class EnrolledClassDetailsViewController: NSViewController {
|
|
5747
|
5746
|
return body
|
|
5748
|
5747
|
}
|
|
5749
|
5748
|
|
|
5750
|
|
- private func makeCommentRow() -> NSView {
|
|
|
5749
|
+ private func makeStreamFooterActionButton(title: String, systemSymbol: String, url: URL) -> NSView {
|
|
5751
|
5750
|
let divider = NSBox()
|
|
5752
|
5751
|
divider.boxType = .separator
|
|
5753
|
5752
|
divider.translatesAutoresizingMaskIntoConstraints = false
|
|
5754
|
|
-
|
|
5755
|
|
- let comment = NSTextField(labelWithString: "Add comment")
|
|
5756
|
|
- comment.font = NSFont.systemFont(ofSize: 13, weight: .semibold)
|
|
5757
|
|
- comment.textColor = palette.primaryBlue
|
|
5758
|
|
-
|
|
5759
|
|
- let icon = NSImageView()
|
|
5760
|
|
- icon.translatesAutoresizingMaskIntoConstraints = false
|
|
5761
|
|
- icon.image = NSImage(systemSymbolName: "bubble.left.and.bubble.right", accessibilityDescription: nil)
|
|
5762
|
|
- icon.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 13, weight: .medium)
|
|
5763
|
|
- icon.contentTintColor = palette.primaryBlue
|
|
5764
|
|
- icon.widthAnchor.constraint(equalToConstant: 15).isActive = true
|
|
5765
|
|
- icon.heightAnchor.constraint(equalToConstant: 15).isActive = true
|
|
5766
|
|
-
|
|
5767
|
|
- let row = NSStackView(views: [icon, comment])
|
|
5768
|
|
- row.orientation = .horizontal
|
|
5769
|
|
- row.alignment = .centerY
|
|
5770
|
|
- row.spacing = 8
|
|
5771
|
|
-
|
|
5772
|
|
- let container = NSStackView(views: [divider, row])
|
|
|
5753
|
+ let actionButton = HoverButton(title: title, target: self, action: #selector(openLinkPressed(_:)))
|
|
|
5754
|
+ actionButton.translatesAutoresizingMaskIntoConstraints = false
|
|
|
5755
|
+ actionButton.isBordered = false
|
|
|
5756
|
+ actionButton.bezelStyle = .regularSquare
|
|
|
5757
|
+ actionButton.identifier = NSUserInterfaceItemIdentifier(url.absoluteString)
|
|
|
5758
|
+ actionButton.wantsLayer = true
|
|
|
5759
|
+ actionButton.layer?.cornerRadius = 8
|
|
|
5760
|
+ actionButton.layer?.backgroundColor = NSColor.clear.cgColor
|
|
|
5761
|
+ actionButton.font = NSFont.systemFont(ofSize: 13, weight: .semibold)
|
|
|
5762
|
+ actionButton.contentTintColor = palette.primaryBlue
|
|
|
5763
|
+ actionButton.image = NSImage(systemSymbolName: systemSymbol, accessibilityDescription: title)
|
|
|
5764
|
+ actionButton.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 13, weight: .semibold)
|
|
|
5765
|
+ actionButton.imagePosition = .imageLeading
|
|
|
5766
|
+ actionButton.imageHugsTitle = true
|
|
|
5767
|
+ actionButton.alignment = .left
|
|
|
5768
|
+ actionButton.lineBreakMode = .byTruncatingTail
|
|
|
5769
|
+ actionButton.heightAnchor.constraint(equalToConstant: 28).isActive = true
|
|
|
5770
|
+
|
|
|
5771
|
+ let baseHover = NSColor.clear
|
|
|
5772
|
+ let hoverBg = palette.inputBackground.blended(withFraction: 0.20, of: palette.primaryBlue) ?? palette.inputBackground
|
|
|
5773
|
+ actionButton.onHoverChanged = { [weak actionButton] hovering in
|
|
|
5774
|
+ actionButton?.layer?.backgroundColor = (hovering ? hoverBg : baseHover).cgColor
|
|
|
5775
|
+ }
|
|
|
5776
|
+ actionButton.onHoverChanged?(false)
|
|
|
5777
|
+
|
|
|
5778
|
+ let container = NSStackView(views: [divider, actionButton])
|
|
|
5779
|
+ container.translatesAutoresizingMaskIntoConstraints = false
|
|
5773
|
5780
|
container.orientation = .vertical
|
|
5774
|
5781
|
container.alignment = .width
|
|
5775
|
|
- container.spacing = 10
|
|
|
5782
|
+ container.spacing = 8
|
|
5776
|
5783
|
return container
|
|
5777
|
5784
|
}
|
|
5778
|
5785
|
|
|
|
@@ -5834,26 +5841,6 @@ private final class EnrolledClassDetailsViewController: NSViewController {
|
|
5834
|
5841
|
return preview
|
|
5835
|
5842
|
}
|
|
5836
|
5843
|
|
|
5837
|
|
- private func makeInlineActionButton(title: String, url: URL) -> NSButton {
|
|
5838
|
|
- let open = HoverButton(title: title, target: self, action: #selector(openLinkPressed(_:)))
|
|
5839
|
|
- open.translatesAutoresizingMaskIntoConstraints = false
|
|
5840
|
|
- open.bezelStyle = .inline
|
|
5841
|
|
- open.identifier = NSUserInterfaceItemIdentifier(url.absoluteString)
|
|
5842
|
|
- open.font = NSFont.systemFont(ofSize: 12, weight: .semibold)
|
|
5843
|
|
- open.wantsLayer = true
|
|
5844
|
|
- open.layer?.cornerRadius = 8
|
|
5845
|
|
- open.layer?.backgroundColor = NSColor.clear.cgColor
|
|
5846
|
|
- open.onHoverChanged = { [weak open] hovering in
|
|
5847
|
|
- guard let open else { return }
|
|
5848
|
|
- let bg = hovering
|
|
5849
|
|
- ? (self.palette.inputBackground.blended(withFraction: 0.18, of: self.palette.primaryBlue) ?? self.palette.inputBackground)
|
|
5850
|
|
- : NSColor.clear
|
|
5851
|
|
- open.layer?.backgroundColor = bg.cgColor
|
|
5852
|
|
- }
|
|
5853
|
|
- open.onHoverChanged?(false)
|
|
5854
|
|
- return open
|
|
5855
|
|
- }
|
|
5856
|
|
-
|
|
5857
|
5844
|
private func makeStreamCardShell() -> NSView {
|
|
5858
|
5845
|
let card = HoverTrackingView()
|
|
5859
|
5846
|
card.translatesAutoresizingMaskIntoConstraints = false
|
|
|
@@ -5876,7 +5863,7 @@ private final class EnrolledClassDetailsViewController: NSViewController {
|
|
5876
|
5863
|
return card
|
|
5877
|
5864
|
}
|
|
5878
|
5865
|
|
|
5879
|
|
- private func wrapInStreamCard(_ content: NSView) -> NSView {
|
|
|
5866
|
+ private func wrapInStreamCard(_ content: NSView, url: URL? = nil) -> NSView {
|
|
5880
|
5867
|
let card = makeStreamCardShell()
|
|
5881
|
5868
|
card.addSubview(content)
|
|
5882
|
5869
|
NSLayoutConstraint.activate([
|
|
|
@@ -5886,7 +5873,22 @@ private final class EnrolledClassDetailsViewController: NSViewController {
|
|
5886
|
5873
|
content.bottomAnchor.constraint(equalTo: card.bottomAnchor, constant: -10),
|
|
5887
|
5874
|
card.widthAnchor.constraint(greaterThanOrEqualToConstant: 220)
|
|
5888
|
5875
|
])
|
|
5889
|
|
- return card
|
|
|
5876
|
+ guard let url else { return card }
|
|
|
5877
|
+
|
|
|
5878
|
+ let hit = HoverButton(title: "", target: self, action: #selector(openLinkPressed(_:)))
|
|
|
5879
|
+ hit.translatesAutoresizingMaskIntoConstraints = false
|
|
|
5880
|
+ hit.isBordered = false
|
|
|
5881
|
+ hit.bezelStyle = .regularSquare
|
|
|
5882
|
+ hit.identifier = NSUserInterfaceItemIdentifier(url.absoluteString)
|
|
|
5883
|
+ hit.toolTip = url.absoluteString
|
|
|
5884
|
+ hit.addSubview(card)
|
|
|
5885
|
+ NSLayoutConstraint.activate([
|
|
|
5886
|
+ card.leadingAnchor.constraint(equalTo: hit.leadingAnchor),
|
|
|
5887
|
+ card.trailingAnchor.constraint(equalTo: hit.trailingAnchor),
|
|
|
5888
|
+ card.topAnchor.constraint(equalTo: hit.topAnchor),
|
|
|
5889
|
+ card.bottomAnchor.constraint(equalTo: hit.bottomAnchor)
|
|
|
5890
|
+ ])
|
|
|
5891
|
+ return hit
|
|
5890
|
5892
|
}
|
|
5891
|
5893
|
|
|
5892
|
5894
|
private func timeText(_ date: Date?) -> String {
|