redesign bottom bar
This commit is contained in:
@@ -6,6 +6,7 @@ struct SybilChatTranscriptView: View {
|
||||
var isLoading: Bool
|
||||
var isSending: Bool
|
||||
var topContentInset: CGFloat = 0
|
||||
var bottomContentInset: CGFloat = 0
|
||||
@State private var hasHandledInitialTranscriptScroll = false
|
||||
|
||||
private var hasPendingAssistant: Bool {
|
||||
@@ -50,7 +51,7 @@ struct SybilChatTranscriptView: View {
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.top, 18 + topContentInset)
|
||||
.padding(.bottom, 18)
|
||||
.padding(.bottom, 18 + bottomContentInset)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.scrollDismissesKeyboard(.interactively)
|
||||
|
||||
@@ -7,6 +7,7 @@ struct SybilSearchResultsView: View {
|
||||
var isRunning: Bool
|
||||
var isStartingChat: Bool = false
|
||||
var topContentInset: CGFloat = 0
|
||||
var bottomContentInset: CGFloat = 0
|
||||
var onStartChat: (() -> Void)? = nil
|
||||
|
||||
var body: some View {
|
||||
@@ -100,7 +101,7 @@ struct SybilSearchResultsView: View {
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.top, 20 + topContentInset)
|
||||
.padding(.bottom, 20)
|
||||
.padding(.bottom, 20 + bottomContentInset)
|
||||
}
|
||||
.scrollDismissesKeyboard(.interactively)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
@@ -35,6 +35,7 @@ struct SybilWorkspaceView: View {
|
||||
@State private var newChatSwipeFeedbackGenerator: UIImpactFeedbackGenerator?
|
||||
|
||||
private let customWorkspaceNavigationContentInset: CGFloat = 96
|
||||
private let composerOverlayContentInset: CGFloat = 112
|
||||
|
||||
private var isSettingsSelected: Bool {
|
||||
if case .settings = viewModel.selectedItem {
|
||||
@@ -149,7 +150,7 @@ struct SybilWorkspaceView: View {
|
||||
.overlay(SybilTheme.border)
|
||||
}
|
||||
|
||||
Group {
|
||||
ZStack(alignment: .bottom) {
|
||||
if isSettingsSelected {
|
||||
SybilSettingsView(viewModel: viewModel)
|
||||
} else if viewModel.isSearchMode {
|
||||
@@ -158,7 +159,8 @@ struct SybilWorkspaceView: View {
|
||||
isLoading: viewModel.isLoadingSelection,
|
||||
isRunning: viewModel.isSending,
|
||||
isStartingChat: viewModel.isCreatingSearchChat,
|
||||
topContentInset: showsCustomWorkspaceNavigation ? customWorkspaceNavigationContentInset : 0
|
||||
topContentInset: showsCustomWorkspaceNavigation ? customWorkspaceNavigationContentInset : 0,
|
||||
bottomContentInset: viewModel.showsComposer ? composerOverlayContentInset : 0
|
||||
) {
|
||||
Task {
|
||||
await viewModel.startChatFromSelectedSearch()
|
||||
@@ -169,10 +171,15 @@ struct SybilWorkspaceView: View {
|
||||
messages: viewModel.displayedMessages,
|
||||
isLoading: viewModel.isLoadingSelection,
|
||||
isSending: viewModel.isSending,
|
||||
topContentInset: showsCustomWorkspaceNavigation ? customWorkspaceNavigationContentInset : 0
|
||||
topContentInset: showsCustomWorkspaceNavigation ? customWorkspaceNavigationContentInset : 0,
|
||||
bottomContentInset: viewModel.showsComposer ? composerOverlayContentInset : 0
|
||||
)
|
||||
.id(transcriptScrollContextID)
|
||||
}
|
||||
|
||||
if viewModel.showsComposer {
|
||||
composerBar
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background {
|
||||
@@ -193,12 +200,6 @@ struct SybilWorkspaceView: View {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if viewModel.showsComposer {
|
||||
Divider()
|
||||
.overlay(SybilTheme.border)
|
||||
composerBar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +502,7 @@ struct SybilWorkspaceView: View {
|
||||
}
|
||||
|
||||
TextField(
|
||||
viewModel.isSearchMode ? "Search the web" : "Message Sybil",
|
||||
viewModel.isSearchMode ? "Search the web" : "Enter Prompt",
|
||||
text: $viewModel.composer,
|
||||
axis: .vertical
|
||||
)
|
||||
@@ -518,10 +519,7 @@ struct SybilWorkspaceView: View {
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.fill(SybilTheme.composerGradient)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.stroke(SybilTheme.primary.opacity(0.34), lineWidth: 1)
|
||||
)
|
||||
.opacity(0.98)
|
||||
)
|
||||
.foregroundStyle(SybilTheme.text)
|
||||
|
||||
@@ -546,23 +544,19 @@ struct SybilWorkspaceView: View {
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.vertical, 12)
|
||||
.background(
|
||||
LinearGradient(
|
||||
colors: [
|
||||
SybilTheme.background.opacity(0.18),
|
||||
SybilTheme.background.opacity(0.96)
|
||||
],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom
|
||||
)
|
||||
)
|
||||
.padding(.top, 34)
|
||||
.padding(.bottom, 12)
|
||||
.background(alignment: .bottom) {
|
||||
SybilComposerFadeBackground()
|
||||
.allowsHitTesting(false)
|
||||
}
|
||||
.overlay {
|
||||
if isComposerDropTargeted && !viewModel.isSearchMode {
|
||||
RoundedRectangle(cornerRadius: 18)
|
||||
.stroke(SybilTheme.accent.opacity(0.78), style: StrokeStyle(lineWidth: 1.5, dash: [7, 5]))
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.vertical, 10)
|
||||
.padding(.top, 32)
|
||||
.padding(.bottom, 10)
|
||||
}
|
||||
}
|
||||
.onDrop(of: [UTType.fileURL.identifier, UTType.image.identifier], isTargeted: $isComposerDropTargeted) { providers in
|
||||
@@ -982,6 +976,60 @@ private extension UIView {
|
||||
}
|
||||
}
|
||||
|
||||
private struct SybilComposerFadeBackground: View {
|
||||
var body: some View {
|
||||
ZStack(alignment: .bottomLeading) {
|
||||
LinearGradient(
|
||||
colors: [
|
||||
Color.clear,
|
||||
SybilTheme.background.opacity(0.30),
|
||||
SybilTheme.background.opacity(0.86),
|
||||
SybilTheme.background.opacity(0.86),
|
||||
SybilTheme.background.opacity(0.98)
|
||||
],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom
|
||||
)
|
||||
|
||||
LinearGradient(
|
||||
colors: [
|
||||
SybilTheme.primary.opacity(0.18),
|
||||
SybilTheme.surface.opacity(0.16),
|
||||
SybilTheme.accent.opacity(0.08)
|
||||
],
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
.mask(
|
||||
LinearGradient(
|
||||
colors: [
|
||||
Color.clear,
|
||||
Color.black.opacity(0.42),
|
||||
Color.black
|
||||
],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom
|
||||
)
|
||||
)
|
||||
.blendMode(.screen)
|
||||
|
||||
RadialGradient(
|
||||
colors: [
|
||||
SybilTheme.primary.opacity(0.28),
|
||||
SybilTheme.primary.opacity(0.08),
|
||||
Color.clear
|
||||
],
|
||||
center: .bottomLeading,
|
||||
startRadius: 8,
|
||||
endRadius: 180
|
||||
)
|
||||
.blendMode(.screen)
|
||||
.offset(x: -42, y: 42)
|
||||
}
|
||||
.ignoresSafeArea(edges: .bottom)
|
||||
}
|
||||
}
|
||||
|
||||
private struct SybilNavigationIcon: View {
|
||||
var systemImage: String
|
||||
|
||||
@@ -1024,6 +1072,7 @@ private struct SybilNavigationFadeBackground: View {
|
||||
.blendMode(.screen)
|
||||
.offset(x: -44, y: -46)
|
||||
}
|
||||
.frame(height: 200.0)
|
||||
.ignoresSafeArea(edges: .top)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user