chore: enabled cancel requests and clear input
703517bf
2 file(s) · +48 −12
| 22 | 22 | let onBack: () -> Void |
|
| 23 | 23 | let onForward: () -> Void |
|
| 24 | 24 | let onSubmitURL: () -> Void |
|
| 25 | + | let onCancel: () -> Void |
|
| 25 | 26 | let onDismissKeyboard: () -> Void |
|
| 26 | 27 | let onShowTabs: () -> Void |
|
| 27 | 28 | let onNewTab: () -> Void |
|
| 92 | 93 | } |
|
| 93 | 94 | ||
| 94 | 95 | private var urlTextField: some View { |
|
| 95 | - | TextField("gemini:// or search", text: $urlText) |
|
| 96 | - | .focused(isURLFocused) |
|
| 97 | - | .autocapitalization(.none) |
|
| 98 | - | .disableAutocorrection(true) |
|
| 99 | - | .keyboardType(.webSearch) |
|
| 100 | - | .submitLabel(.go) |
|
| 101 | - | .onSubmit { |
|
| 102 | - | isURLFocused.wrappedValue = false |
|
| 103 | - | onSubmitURL() |
|
| 96 | + | HStack(spacing: 0) { |
|
| 97 | + | TextField("gemini:// or search", text: $urlText) |
|
| 98 | + | .focused(isURLFocused) |
|
| 99 | + | .autocapitalization(.none) |
|
| 100 | + | .disableAutocorrection(true) |
|
| 101 | + | .keyboardType(.webSearch) |
|
| 102 | + | .submitLabel(.go) |
|
| 103 | + | .onSubmit { |
|
| 104 | + | isURLFocused.wrappedValue = false |
|
| 105 | + | onSubmitURL() |
|
| 106 | + | } |
|
| 107 | + | .padding(.leading, 12) |
|
| 108 | + | .padding(.vertical, 12) |
|
| 109 | + | ||
| 110 | + | if isLoading { |
|
| 111 | + | Button(action: onCancel) { |
|
| 112 | + | Image(systemName: "xmark.circle.fill") |
|
| 113 | + | .font(.body) |
|
| 114 | + | .foregroundStyle(themeSettings.toolbarButtonColor.opacity(0.7)) |
|
| 115 | + | } |
|
| 116 | + | .padding(.horizontal, 10) |
|
| 117 | + | .transition(.opacity.combined(with: .scale(scale: 0.8))) |
|
| 118 | + | } else if isURLFocused.wrappedValue && !urlText.isEmpty { |
|
| 119 | + | Button { |
|
| 120 | + | urlText = "" |
|
| 121 | + | } label: { |
|
| 122 | + | Image(systemName: "xmark.circle.fill") |
|
| 123 | + | .font(.body) |
|
| 124 | + | .foregroundStyle(themeSettings.toolbarButtonColor.opacity(0.7)) |
|
| 125 | + | } |
|
| 126 | + | .padding(.horizontal, 10) |
|
| 127 | + | .transition(.opacity.combined(with: .scale(scale: 0.8))) |
|
| 128 | + | } else { |
|
| 129 | + | Spacer() |
|
| 130 | + | .frame(width: 12) |
|
| 104 | 131 | } |
|
| 105 | - | .padding(.horizontal, 12) |
|
| 106 | - | .padding(.vertical, 12) |
|
| 107 | - | .glassEffect(.regular, in: .capsule) |
|
| 132 | + | } |
|
| 133 | + | .glassEffect(.regular, in: .capsule) |
|
| 134 | + | .animation(.easeInOut(duration: 0.2), value: isLoading) |
|
| 135 | + | .animation(.easeInOut(duration: 0.2), value: isURLFocused.wrappedValue) |
|
| 136 | + | .animation(.easeInOut(duration: 0.2), value: urlText.isEmpty) |
|
| 108 | 137 | } |
|
| 109 | 138 | ||
| 110 | 139 | private var dismissButton: some View { |
|
| 95 | 95 | onBack: goBack, |
|
| 96 | 96 | onForward: goForward, |
|
| 97 | 97 | onSubmitURL: { navigateTo(urlText) }, |
|
| 98 | + | onCancel: cancelCurrentRequest, |
|
| 98 | 99 | onDismissKeyboard: { isURLFocused = false }, |
|
| 99 | 100 | onShowTabs: { showTabs = true }, |
|
| 100 | 101 | onNewTab: { |
|
| 321 | 322 | historyIndex += 1 |
|
| 322 | 323 | urlText = history[historyIndex] |
|
| 323 | 324 | fetchContent(addToHistory: false) |
|
| 325 | + | } |
|
| 326 | + | ||
| 327 | + | private func cancelCurrentRequest() { |
|
| 328 | + | currentFetchTask?.cancel() |
|
| 329 | + | currentFetchTask = nil |
|
| 330 | + | isLoading = false |
|
| 324 | 331 | } |
|
| 325 | 332 | ||
| 326 | 333 | private func addToNavigationHistory(url: String) { |
|