Skip to content

Commit d805a77

Browse files
Unified about window (#1010)
1 parent fd2c961 commit d805a77

11 files changed

Lines changed: 389 additions & 152 deletions

File tree

CodeEdit.xcodeproj/project.pbxproj

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,9 @@
315315
6C05A8AF284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C05A8AE284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift */; };
316316
6C14CEB028777D3C001468FE /* FindNavigatorListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C14CEAF28777D3C001468FE /* FindNavigatorListViewController.swift */; };
317317
6C14CEB32877A68F001468FE /* FindNavigatorMatchListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C14CEB22877A68F001468FE /* FindNavigatorMatchListCell.swift */; };
318+
6C4104E3297C87A000F472BA /* BlurButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4104E2297C87A000F472BA /* BlurButtonStyle.swift */; };
319+
6C4104E6297C884F00F472BA /* AboutDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4104E5297C884F00F472BA /* AboutDetailView.swift */; };
320+
6C4104E9297C970F00F472BA /* AboutDefaultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4104E8297C970F00F472BA /* AboutDefaultView.swift */; };
318321
6C48D8F22972DAFC00D6D205 /* Env+IsFullscreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C48D8F12972DAFC00D6D205 /* Env+IsFullscreen.swift */; };
319322
6C48D8F42972DB1A00D6D205 /* Env+Window.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C48D8F32972DB1A00D6D205 /* Env+Window.swift */; };
320323
6C48D8F72972E5F300D6D205 /* WindowObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C48D8F62972E5F300D6D205 /* WindowObserver.swift */; };
@@ -702,6 +705,9 @@
702705
6C05A8AE284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+Listeners.swift"; sourceTree = "<group>"; };
703706
6C14CEAF28777D3C001468FE /* FindNavigatorListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindNavigatorListViewController.swift; sourceTree = "<group>"; };
704707
6C14CEB22877A68F001468FE /* FindNavigatorMatchListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindNavigatorMatchListCell.swift; sourceTree = "<group>"; };
708+
6C4104E2297C87A000F472BA /* BlurButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurButtonStyle.swift; sourceTree = "<group>"; };
709+
6C4104E5297C884F00F472BA /* AboutDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutDetailView.swift; sourceTree = "<group>"; };
710+
6C4104E8297C970F00F472BA /* AboutDefaultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutDefaultView.swift; sourceTree = "<group>"; };
705711
6C48D8F12972DAFC00D6D205 /* Env+IsFullscreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Env+IsFullscreen.swift"; sourceTree = "<group>"; };
706712
6C48D8F32972DB1A00D6D205 /* Env+Window.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Env+Window.swift"; sourceTree = "<group>"; };
707713
6C48D8F62972E5F300D6D205 /* WindowObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowObserver.swift; sourceTree = "<group>"; };
@@ -1049,6 +1055,9 @@
10491055
isa = PBXGroup;
10501056
children = (
10511057
582213EF291834A500EFE361 /* AboutView.swift */,
1058+
6C4104E8297C970F00F472BA /* AboutDefaultView.swift */,
1059+
6C4104E5297C884F00F472BA /* AboutDetailView.swift */,
1060+
6C4104E2297C87A000F472BA /* BlurButtonStyle.swift */,
10521061
6C97EBCE297876E500302F95 /* AboutWindowController.swift */,
10531062
);
10541063
path = Views;
@@ -1057,9 +1066,9 @@
10571066
5831E3C52933E6CB00D5A6D2 /* Features */ = {
10581067
isa = PBXGroup;
10591068
children = (
1060-
284DC84B2978B5EB00BF2770 /* Contributors */,
10611069
582213EE2918345500EFE361 /* About */,
10621070
5878DA7D291862BC00DD95A3 /* Acknowledgements */,
1071+
284DC84B2978B5EB00BF2770 /* Contributors */,
10631072
58F2EA9E292FB2B0004A9BDE /* AppPreferences */,
10641073
5878DAAB291D627C00DD95A3 /* Breadcrumbs */,
10651074
587B9D50292FC27A00AC7927 /* CodeEditExtension */,
@@ -2616,6 +2625,7 @@
26162625
58F2EB08292FB2B0004A9BDE /* TextEditingPreferences.swift in Sources */,
26172626
201169DB2837B34000F92B46 /* SourceControlNavigatorChangedFileView.swift in Sources */,
26182627
5882252E292C280D00E83CDE /* StatusBarMaximizeButton.swift in Sources */,
2628+
6C4104E9297C970F00F472BA /* AboutDefaultView.swift in Sources */,
26192629
587B9E6F29301D8F00AC7927 /* GitLabProjectAccess.swift in Sources */,
26202630
587B9E6929301D8F00AC7927 /* GitLabEvent.swift in Sources */,
26212631
587B9E5E29301D8F00AC7927 /* GitLabCommitRouter.swift in Sources */,
@@ -2707,6 +2717,7 @@
27072717
587B9E6429301D8F00AC7927 /* GitLabCommit.swift in Sources */,
27082718
58A5DFA229339F6400D1BD5D /* KeybindingManager.swift in Sources */,
27092719
58AFAA2E2933C69E00482B53 /* TabBarItemRepresentable.swift in Sources */,
2720+
6C4104E6297C884F00F472BA /* AboutDetailView.swift in Sources */,
27102721
587B9E7A29301D8F00AC7927 /* GitHubReviewsRouter.swift in Sources */,
27112722
04540D5E27DD08C300E91B77 /* WorkspaceView.swift in Sources */,
27122723
DE6F77872813625500D00A76 /* TabBarDivider.swift in Sources */,
@@ -2864,6 +2875,7 @@
28642875
58F2EAE8292FB2B0004A9BDE /* TerminalPreferencesView.swift in Sources */,
28652876
58AFAA2F2933C69E00482B53 /* TabBarItemID.swift in Sources */,
28662877
28FFE1BF27E3A441001939DB /* NavigatorSidebarToolbarBottom.swift in Sources */,
2878+
6C4104E3297C87A000F472BA /* BlurButtonStyle.swift in Sources */,
28672879
58F2EAFA292FB2B0004A9BDE /* GitLabHostedLoginView.swift in Sources */,
28682880
);
28692881
runOnlyForDeploymentPostprocessing = 0;
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
//
2+
// AboutDefaultView.swift
3+
// CodeEdit
4+
//
5+
// Created by Wouter Hennen on 21/01/2023.
6+
//
7+
8+
import SwiftUI
9+
10+
struct AboutDefaultView: View {
11+
private var appVersion: String {
12+
Bundle.versionString ?? "No Version"
13+
}
14+
15+
private var appBuild: String {
16+
Bundle.buildString ?? "No Build"
17+
}
18+
19+
private var appVersionPostfix: String {
20+
Bundle.versionPostfix ?? ""
21+
}
22+
23+
@Binding var aboutMode: AboutMode
24+
var namespace: Namespace.ID
25+
@Environment(\.colorScheme) var colorScheme
26+
27+
private static var licenseURL = URL(string: "https://github.com/CodeEditApp/CodeEdit/blob/main/LICENSE.md")!
28+
29+
let smallTitlebarHeight: CGFloat = 28
30+
let mediumTitlebarHeight: CGFloat = 113
31+
let largeTitlebarHeight: CGFloat = 231
32+
33+
var body: some View {
34+
VStack(spacing: 0) {
35+
Image(nsImage: NSApp.applicationIconImage)
36+
.resizable()
37+
.matchedGeometryEffect(id: "AppIcon", in: namespace)
38+
.frame(width: 128, height: 128)
39+
.padding(.top, 16)
40+
.padding(.bottom, 8)
41+
42+
VStack(spacing: 0) {
43+
Text("CodeEdit")
44+
.matchedGeometryEffect(id: "Title", in: namespace, properties: .position, anchor: .center)
45+
.foregroundColor(.primary)
46+
.font(.system(
47+
size: 26,
48+
weight: .bold
49+
))
50+
Text("Version \(appVersion)\(appVersionPostfix) (\(appBuild))")
51+
.textSelection(.enabled)
52+
.foregroundColor(Color(.tertiaryLabelColor))
53+
.font(.body)
54+
.blendMode(colorScheme == .dark ? .plusLighter : .plusDarker)
55+
.padding(.top, 4)
56+
.matchedGeometryEffect(
57+
id: "Title",
58+
in: namespace,
59+
properties: .position,
60+
anchor: UnitPoint(x: 0.5, y: -0.75)
61+
)
62+
}
63+
.padding(.horizontal)
64+
}
65+
.padding(24)
66+
67+
VStack {
68+
Spacer()
69+
VStack {
70+
Button {
71+
aboutMode = .contributors
72+
} label: {
73+
Text("Contributors")
74+
.foregroundColor(.primary)
75+
.frame(maxWidth: .infinity)
76+
}
77+
.controlSize(.large)
78+
.buttonStyle(.blur)
79+
80+
Button {
81+
aboutMode = .acknowledgements
82+
} label: {
83+
Text("Acknowledgements")
84+
.foregroundColor(.primary)
85+
.frame(maxWidth: .infinity)
86+
}
87+
.controlSize(.large)
88+
.buttonStyle(.blur)
89+
90+
VStack(spacing: 2) {
91+
Link(destination: Self.licenseURL) {
92+
Text("MIT License")
93+
.underline()
94+
95+
}
96+
Text(Bundle.copyrightString ?? "")
97+
}
98+
.textSelection(.disabled)
99+
.font(.system(size: 11, weight: .regular))
100+
.foregroundColor(Color(.tertiaryLabelColor))
101+
.blendMode(colorScheme == .dark ? .plusLighter : .plusDarker)
102+
.padding(.top, 12)
103+
.padding(.bottom, 24)
104+
}
105+
.matchedGeometryEffect(id: "Titlebar", in: namespace, properties: .position, anchor: .top)
106+
.matchedGeometryEffect(id: "ScrollView", in: namespace, properties: .position, anchor: .top)
107+
}
108+
.padding(.horizontal)
109+
}
110+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
//
2+
// AboutDetailView.swift
3+
// CodeEdit
4+
//
5+
// Created by Wouter Hennen on 21/01/2023.
6+
//
7+
8+
import SwiftUI
9+
10+
struct AboutDetailView<Content: View>: View {
11+
var title: String
12+
13+
@Binding var aboutMode: AboutMode
14+
15+
var namespace: Namespace.ID
16+
17+
@ViewBuilder
18+
var content: Content
19+
20+
let smallTitlebarHeight: CGFloat = 28
21+
let mediumTitlebarHeight: CGFloat = 113
22+
let largeTitlebarHeight: CGFloat = 231
23+
24+
var maxScrollOffset: CGFloat {
25+
smallTitlebarHeight - mediumTitlebarHeight
26+
}
27+
28+
var currentOffset: CGFloat {
29+
getScrollAdjustedValue(
30+
minValue: 22,
31+
maxValue: 14,
32+
minOffset: 0,
33+
maxOffset: maxScrollOffset
34+
)
35+
}
36+
37+
@State private var scrollOffset: CGFloat = 0
38+
39+
var body: some View {
40+
VStack {
41+
Spacer(minLength: smallTitlebarHeight + 1)
42+
OffsettableScrollView(showsIndicator: false) { offset in
43+
scrollOffset = offset.y
44+
} content: {
45+
Spacer(minLength: mediumTitlebarHeight - smallTitlebarHeight - 1 + 8)
46+
content
47+
.padding(.horizontal)
48+
.padding(.bottom, 8)
49+
}
50+
.frame(maxWidth: .infinity)
51+
.matchedGeometryEffect(id: "ScrollView", in: namespace, properties: .position, anchor: .top)
52+
.clipShape(Rectangle())
53+
}
54+
55+
VStack(spacing: 0) {
56+
Image(nsImage: NSApp.applicationIconImage)
57+
.resizable()
58+
.matchedGeometryEffect(id: "AppIcon", in: namespace)
59+
.frame(
60+
width: getScrollAdjustedValue(
61+
minValue: 48,
62+
maxValue: 0,
63+
minOffset: 0,
64+
maxOffset: maxScrollOffset
65+
),
66+
height: getScrollAdjustedValue(
67+
minValue: 48,
68+
maxValue: 0,
69+
minOffset: 0,
70+
maxOffset: maxScrollOffset
71+
)
72+
)
73+
.opacity(
74+
getScrollAdjustedValue(
75+
minValue: 1,
76+
maxValue: 0,
77+
minOffset: 0,
78+
maxOffset: maxScrollOffset
79+
)
80+
)
81+
.padding(.top, getScrollAdjustedValue(
82+
minValue: smallTitlebarHeight,
83+
maxValue: 0,
84+
minOffset: 0,
85+
maxOffset: maxScrollOffset
86+
))
87+
.padding(.bottom, getScrollAdjustedValue(
88+
minValue: 5,
89+
maxValue: 0,
90+
minOffset: 0,
91+
maxOffset: maxScrollOffset
92+
))
93+
94+
Button {
95+
aboutMode = .about
96+
} label: {
97+
Text(title)
98+
.foregroundColor(.primary)
99+
.font(.system(
100+
size: getScrollAdjustedValue(
101+
minValue: 20,
102+
maxValue: 14,
103+
minOffset: 0,
104+
maxOffset: maxScrollOffset
105+
),
106+
weight: .bold
107+
))
108+
109+
.fixedSize(horizontal: true, vertical: false)
110+
.frame(minHeight: smallTitlebarHeight)
111+
.padding(.horizontal, 13)
112+
.overlay(alignment: .leading) {
113+
Image(systemName: "chevron.left")
114+
.foregroundColor(.secondary)
115+
.padding(.trailing)
116+
}
117+
.contentShape(Rectangle())
118+
.matchedGeometryEffect(id: "Title", in: namespace, properties: .position, anchor: .center)
119+
}
120+
.buttonStyle(.plain)
121+
122+
Divider()
123+
.opacity(getScrollAdjustedValue(
124+
minValue: 0,
125+
maxValue: 1,
126+
minOffset: 0,
127+
maxOffset: maxScrollOffset
128+
))
129+
}
130+
.padding(0)
131+
.frame(maxWidth: .infinity)
132+
.matchedGeometryEffect(id: "Titlebar", in: namespace, properties: .position, anchor: .bottom)
133+
}
134+
135+
func getScrollAdjustedValue(
136+
minValue: CGFloat,
137+
maxValue: CGFloat,
138+
minOffset: CGFloat,
139+
maxOffset: CGFloat
140+
) -> CGFloat {
141+
let valueRange = maxValue - minValue
142+
let offsetRange = maxOffset - minOffset
143+
let currentOffset = scrollOffset
144+
let percentage = (currentOffset - minOffset) / offsetRange
145+
let value = minValue + (valueRange * percentage)
146+
147+
if currentOffset <= maxOffset {
148+
return maxValue
149+
}
150+
if value < 0 {
151+
return 0
152+
}
153+
return value
154+
}
155+
}

0 commit comments

Comments
 (0)