Skip to content

Commit ff64ca4

Browse files
committed
added first omnibar iteration:
1 parent 87e9085 commit ff64ca4

File tree

5 files changed

+286
-173
lines changed

5 files changed

+286
-173
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright (c) 2025 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.duckchat.impl.ui
18+
19+
import android.content.Context
20+
import android.util.AttributeSet
21+
import android.widget.FrameLayout
22+
import com.duckduckgo.anvil.annotations.InjectWith
23+
import com.duckduckgo.browser.ui.omnibar.OmnibarType
24+
import com.duckduckgo.browser.ui.tabs.NewTabSwitcherButton
25+
import com.duckduckgo.di.scopes.FragmentScope
26+
import com.duckduckgo.duckchat.impl.R
27+
import com.google.android.material.appbar.AppBarLayout
28+
import dagger.android.support.AndroidSupportInjection
29+
30+
@InjectWith(FragmentScope::class)
31+
class DuckChatOmnibarLayout @JvmOverloads constructor(
32+
context: Context,
33+
attrs: AttributeSet? = null,
34+
defStyle: Int = 0,
35+
) : AppBarLayout(context, attrs, defStyle) {
36+
37+
internal val tabsMenu: NewTabSwitcherButton by lazy { findViewById(R.id.inputFieldTabsMenu) }
38+
internal val fireIconMenu: FrameLayout by lazy { findViewById(R.id.inputFieldFireButton) }
39+
internal val browserMenu: FrameLayout by lazy { findViewById(R.id.inputFieldBrowserMenu) }
40+
41+
private var omnibarItemPressedListener: ItemPressedListener? = null
42+
43+
interface ItemPressedListener {
44+
fun onTabsButtonPressed()
45+
46+
fun onFireButtonPressed()
47+
48+
fun onBrowserMenuPressed()
49+
}
50+
51+
init {
52+
inflate(context, R.layout.view_duck_chat_omnibar, this)
53+
54+
AndroidSupportInjection.inject(this)
55+
56+
val attr = context.theme.obtainStyledAttributes(attrs, R.styleable.DuckChatOmnibarLayout, defStyle, 0)
57+
val omnibarType = OmnibarType.entries[attr.getInt(R.styleable.DuckChatOmnibarLayout_duckOmnibarPosition, 0)]
58+
val isTopPosition = omnibarType == OmnibarType.SINGLE_TOP || omnibarType == OmnibarType.SPLIT
59+
}
60+
61+
fun setOmnibarItemPressedListener(itemPressedListener: ItemPressedListener) {
62+
omnibarItemPressedListener = itemPressedListener
63+
tabsMenu.setOnClickListener {
64+
omnibarItemPressedListener?.onTabsButtonPressed()
65+
}
66+
67+
fireIconMenu.setOnClickListener {
68+
omnibarItemPressedListener?.onFireButtonPressed()
69+
}
70+
71+
browserMenu.setOnClickListener {
72+
omnibarItemPressedListener?.onBrowserMenuPressed()
73+
}
74+
}
75+
76+
fun setTabsCount(tabs: Int) {
77+
tabsMenu.count = tabs
78+
}
79+
}

duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/ui/DuckChatWebViewFragment.kt

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import android.webkit.WebChromeClient.FileChooserParams
3737
import android.webkit.WebSettings
3838
import android.webkit.WebView
3939
import androidx.annotation.AnyThread
40+
import androidx.appcompat.widget.Toolbar
4041
import androidx.core.content.ContextCompat
4142
import androidx.lifecycle.ViewModelProvider
4243
import androidx.lifecycle.lifecycleScope
@@ -160,10 +161,10 @@ open class DuckChatWebViewFragment : DuckDuckGoFragment(R.layout.activity_duck_c
160161
private var pendingUploadTask: ValueCallback<Array<Uri>>? = null
161162

162163
private val root: ViewGroup by lazy { binding.root }
164+
private val toolbar: Toolbar? by lazy { binding.includeToolbar.toolbar }
165+
private val duckChatOmnibar: DuckChatOmnibarLayout? by lazy { binding.omnibarLayoutTop }
163166

164-
// private val toolbar: Toolbar? by lazy { binding.includeToolbar.toolbar }
165167
internal val simpleWebview: WebView by lazy { binding.simpleWebview }
166-
internal val tabSwitcher by lazy { binding.inputFieldTabsMenu }
167168

168169
@SuppressLint("SetJavaScriptEnabled")
169170
override fun onViewCreated(
@@ -172,17 +173,11 @@ open class DuckChatWebViewFragment : DuckDuckGoFragment(R.layout.activity_duck_c
172173
) {
173174
super.onViewCreated(view, savedInstanceState)
174175

175-
// toolbar?.let {
176-
// it.setNavigationIcon(com.duckduckgo.mobile.android.R.drawable.ic_arrow_left_24)
177-
// it.setNavigationOnClickListener {
178-
// requireActivity().onBackPressed()
179-
// }
180-
// it.setTitle(R.string.duck_chat_title)
181-
// }
182-
183176
val url = arguments?.getString(KEY_DUCK_AI_URL) ?: "https://duckduckgo.com/?q=DuckDuckGo+AI+Chat&ia=chat&duckai=5"
184177
val tabs = arguments?.getInt(KEY_DUCK_AI_TABS) ?: 0
185178

179+
configureOmnibar(tabs)
180+
186181
simpleWebview.let {
187182
it.webViewClient = webViewClient
188183
it.webChromeClient = object : WebChromeClient() {
@@ -307,8 +302,6 @@ open class DuckChatWebViewFragment : DuckDuckGoFragment(R.layout.activity_duck_c
307302
pendingUploadTask = null
308303
}
309304

310-
tabSwitcher.count = tabs
311-
312305
// Observe ViewModel commands
313306
viewModel.commands
314307
.onEach { command ->
@@ -325,6 +318,35 @@ open class DuckChatWebViewFragment : DuckDuckGoFragment(R.layout.activity_duck_c
325318
}.launchIn(lifecycleScope)
326319
}
327320

321+
private fun configureOmnibar(tabs: Int) {
322+
if (false) {
323+
toolbar?.let {
324+
it.setNavigationIcon(com.duckduckgo.mobile.android.R.drawable.ic_arrow_left_24)
325+
it.setNavigationOnClickListener {
326+
requireActivity().onBackPressed()
327+
}
328+
it.setTitle(R.string.duck_chat_title)
329+
}
330+
} else {
331+
duckChatOmnibar?.setOmnibarItemPressedListener(
332+
object : DuckChatOmnibarLayout.ItemPressedListener {
333+
override fun onTabsButtonPressed() {
334+
TODO("Not yet implemented")
335+
}
336+
337+
override fun onFireButtonPressed() {
338+
TODO("Not yet implemented")
339+
}
340+
341+
override fun onBrowserMenuPressed() {
342+
TODO("Not yet implemented")
343+
}
344+
},
345+
)
346+
duckChatOmnibar?.setTabsCount(tabs)
347+
}
348+
}
349+
328350
data class FileChooserRequestedParams(
329351
val filePickingMode: Int,
330352
val acceptMimeTypes: List<String>,

duckchat/duckchat-impl/src/main/res/layout/activity_duck_chat_webview.xml

Lines changed: 12 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -23,170 +23,21 @@
2323
android:layout_height="match_parent"
2424
android:orientation="vertical">
2525

26-
<androidx.constraintlayout.widget.ConstraintLayout
27-
android:id="@+id/inputModeWidgetLayout"
28-
android:layout_width="match_parent"
29-
android:layout_height="?attr/actionBarSize"
30-
android:layout_marginStart="@dimen/omnibarCardMarginHorizontal"
31-
android:paddingTop="2dp"
32-
android:orientation="horizontal"
33-
app:layout_constraintEnd_toEndOf="parent"
34-
app:layout_constraintStart_toStartOf="parent"
35-
app:layout_constraintTop_toBottomOf="@id/spacer">
36-
37-
<com.google.android.material.card.MaterialCardView
38-
android:id="@+id/inputModeWidgetCard"
39-
style="@style/Widget.DuckDuckGo.OmnibarCardView"
40-
android:layout_width="0dp"
41-
android:layout_height="wrap_content"
42-
app:cardElevation="0dp"
43-
android:layout_marginTop="2dp"
44-
app:layout_constraintEnd_toStartOf="@id/inputModeMainButtonsContainer"
45-
app:layout_constraintStart_toStartOf="parent"
46-
app:layout_constraintTop_toTopOf="parent"
47-
app:strokeColor="?attr/daxColorAccentBlue"
48-
app:strokeWidth="@dimen/omnibarOutlineWidth">
49-
50-
<LinearLayout
51-
android:layout_width="match_parent"
52-
android:layout_height="wrap_content"
53-
android:orientation="vertical">
54-
55-
<LinearLayout
56-
android:id="@+id/inputModeWidgetCardContent"
57-
android:layout_width="match_parent"
58-
android:layout_height="wrap_content"
59-
android:orientation="horizontal"
60-
android:padding="@dimen/keyline_0">
61-
62-
<ImageView
63-
android:id="@+id/daxIcon"
64-
android:layout_width="@dimen/toolbarIcon"
65-
android:layout_height="@dimen/toolbarIcon"
66-
android:layout_gravity="center"
67-
android:importantForAccessibility="no"
68-
android:scaleType="fitCenter"
69-
app:srcCompat="@drawable/ic_duckai"
70-
tools:visibility="visible" />
71-
72-
<com.duckduckgo.common.ui.view.text.DaxTextView
73-
android:id="@+id/inputField"
74-
android:layout_width="0dp"
75-
android:layout_height="wrap_content"
76-
android:layout_weight="1"
77-
android:layout_gravity="center_vertical"
78-
android:layout_marginStart="10dp"
79-
app:typography="body1"
80-
app:textType="primary"
81-
android:text="Duck.ai" />
82-
83-
<ImageView
84-
android:id="@+id/inputFieldVoiceInputButton"
85-
android:layout_width="@dimen/toolbarIcon"
86-
android:layout_height="@dimen/toolbarIcon"
87-
android:layout_gravity="top"
88-
android:background="@drawable/selectable_item_experimental_background"
89-
android:gravity="center"
90-
android:importantForAccessibility="no"
91-
android:scaleType="center"
92-
android:visibility="gone"
93-
app:srcCompat="@drawable/ic_microphone_24"
94-
tools:visibility="visible" />
95-
96-
<ImageView
97-
android:id="@+id/inputFieldClearText"
98-
android:layout_width="@dimen/toolbarIcon"
99-
android:layout_height="@dimen/toolbarIcon"
100-
android:layout_gravity="top"
101-
android:background="@drawable/selectable_item_experimental_background"
102-
android:gravity="center"
103-
android:importantForAccessibility="no"
104-
android:scaleType="centerInside"
105-
android:visibility="gone"
106-
app:srcCompat="@drawable/ic_close_circle_small_secondary_24" />
107-
108-
</LinearLayout>
109-
110-
<FrameLayout
111-
android:id="@+id/inputScreenButtonsContainer"
112-
android:layout_width="wrap_content"
113-
android:layout_height="wrap_content"
114-
android:layout_gravity="end"
115-
android:layout_marginEnd="8dp"
116-
android:visibility="gone" />
117-
118-
</LinearLayout>
26+
<include
27+
android:id="@+id/includeToolbar"
28+
layout="@layout/include_default_toolbar" />
11929

120-
</com.google.android.material.card.MaterialCardView>
121-
122-
<androidx.constraintlayout.widget.ConstraintLayout
123-
android:id="@+id/inputModeMainButtonsContainer"
124-
android:layout_width="wrap_content"
125-
android:layout_height="@dimen/toolbarIcon"
126-
android:layout_marginStart="@dimen/keyline_2"
127-
app:layout_constraintBottom_toBottomOf="@id/inputModeWidgetCard"
128-
app:layout_constraintEnd_toEndOf="parent"
129-
app:layout_constraintStart_toEndOf="@id/inputModeWidgetCard"
130-
app:layout_constraintTop_toTopOf="@id/inputModeWidgetCard">
131-
132-
<FrameLayout
133-
android:id="@+id/inputFieldFireButton"
134-
android:layout_width="@dimen/toolbarIcon"
135-
android:layout_height="@dimen/toolbarIcon"
136-
android:background="@drawable/selectable_item_experimental_background"
137-
app:layout_constraintBottom_toBottomOf="parent"
138-
app:layout_constraintEnd_toStartOf="@id/inputFieldTabsMenu"
139-
app:layout_constraintStart_toStartOf="parent"
140-
app:layout_constraintTop_toTopOf="parent">
141-
142-
<ImageView
143-
android:id="@+id/fireIconImageView"
144-
android:layout_width="@dimen/bottomNavIcon"
145-
android:layout_height="@dimen/bottomNavIcon"
146-
android:layout_gravity="center"
147-
android:scaleType="center"
148-
android:src="@drawable/ic_fire_24" />
149-
</FrameLayout>
150-
151-
<com.duckduckgo.browser.ui.tabs.NewTabSwitcherButton
152-
android:id="@+id/inputFieldTabsMenu"
153-
android:layout_width="@dimen/toolbarIcon"
154-
android:layout_height="@dimen/toolbarIcon"
155-
app:layout_constraintBottom_toBottomOf="parent"
156-
app:layout_constraintEnd_toStartOf="@id/inputFieldBrowserMenu"
157-
app:layout_constraintStart_toEndOf="@id/inputFieldFireButton"
158-
app:layout_constraintTop_toTopOf="parent" />
159-
160-
<FrameLayout
161-
android:id="@+id/inputFieldBrowserMenu"
162-
android:layout_width="@dimen/toolbarIcon"
163-
android:layout_height="@dimen/toolbarIcon"
164-
android:background="@drawable/selectable_item_experimental_background"
165-
app:layout_constraintBottom_toBottomOf="parent"
166-
app:layout_constraintEnd_toEndOf="parent"
167-
app:layout_constraintStart_toEndOf="@id/inputFieldTabsMenu"
168-
app:layout_constraintTop_toTopOf="parent">
169-
170-
<ImageView
171-
android:id="@+id/browserMenuImageView"
172-
android:layout_width="@dimen/bottomNavIcon"
173-
android:layout_height="@dimen/bottomNavIcon"
174-
android:layout_gravity="center"
175-
android:scaleType="center"
176-
android:src="@drawable/ic_menu_vertical_24" />
177-
178-
</FrameLayout>
179-
180-
</androidx.constraintlayout.widget.ConstraintLayout>
181-
182-
</androidx.constraintlayout.widget.ConstraintLayout>
30+
<com.duckduckgo.duckchat.impl.ui.DuckChatOmnibarLayout
31+
android:id="@+id/omnibarLayoutTop"
32+
android:layout_width="match_parent"
33+
android:layout_height="wrap_content"
34+
android:elevation="1dp"
35+
android:outlineProvider="none"
36+
app:duckOmnibarPosition="top" />
18337

18438
<WebView
18539
android:id="@+id/simpleWebview"
18640
android:layout_width="match_parent"
187-
android:layout_height="match_parent"
188-
app:layout_constraintBottom_toBottomOf="@id/inputModeWidgetCard"
189-
app:layout_constraintEnd_toEndOf="parent"
190-
app:layout_constraintStart_toStartOf="parent" />
41+
android:layout_height="match_parent" />
19142

192-
</LinearLayout>
43+
</LinearLayout>

0 commit comments

Comments
 (0)