Skip to content

Commit eda671e

Browse files
authored
Add Browsing menu
1 parent cb81977 commit eda671e

20 files changed

+427
-96
lines changed

app/src/main/java/com/duckduckgo/app/browser/BrowserActivity.kt

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package com.duckduckgo.app.browser
1818

1919
import android.annotation.SuppressLint
2020
import android.app.DownloadManager
21-
import android.app.DownloadManager.Request.*
21+
import android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED
2222
import android.arch.lifecycle.Observer
2323
import android.arch.lifecycle.ViewModelProviders
2424
import android.content.Context
@@ -46,22 +46,25 @@ import com.duckduckgo.app.privacymonitor.renderer.icon
4646
import com.duckduckgo.app.privacymonitor.ui.PrivacyDashboardActivity
4747
import com.duckduckgo.app.settings.SettingsActivity
4848
import kotlinx.android.synthetic.main.activity_browser.*
49+
import kotlinx.android.synthetic.main.popup_window_brower_menu.view.*
4950
import org.jetbrains.anko.doAsync
5051
import org.jetbrains.anko.toast
5152
import org.jetbrains.anko.uiThread
5253
import timber.log.Timber
5354
import javax.inject.Inject
5455

56+
5557
class BrowserActivity : DuckDuckGoActivity() {
5658

5759
@Inject lateinit var webViewClient: BrowserWebViewClient
5860
@Inject lateinit var webChromeClient: BrowserChromeClient
5961
@Inject lateinit var viewModelFactory: ViewModelFactory
6062

63+
private lateinit var popupMenu: BrowserPopupMenu
64+
6165
private lateinit var autoCompleteSuggestionsAdapter: BrowserAutoCompleteSuggestionsAdapter
6266

6367
private var acceptingRenderUpdates = true
64-
private var addBookmarkMenuItem: MenuItem? = null
6568

6669
private val viewModel: BrowserViewModel by lazy {
6770
ViewModelProviders.of(this, viewModelFactory).get(BrowserViewModel::class.java)
@@ -76,6 +79,7 @@ class BrowserActivity : DuckDuckGoActivity() {
7679
override fun onCreate(savedInstanceState: Bundle?) {
7780
super.onCreate(savedInstanceState)
7881
setContentView(R.layout.activity_browser)
82+
popupMenu = BrowserPopupMenu(layoutInflater)
7983

8084
viewModel.viewState.observe(this, Observer<BrowserViewModel.ViewState> {
8185
it?.let { render(it) }
@@ -163,7 +167,6 @@ class BrowserActivity : DuckDuckGoActivity() {
163167
false -> pageLoadingIndicator.hide()
164168
}
165169

166-
addBookmarkMenuItem?.setEnabled(viewState.canAddBookmarks)
167170
if (shouldUpdateOmnibarTextInput(viewState, viewState.omnibarText)) {
168171
omnibarTextInput.setText(viewState.omnibarText)
169172

@@ -181,6 +184,10 @@ class BrowserActivity : DuckDuckGoActivity() {
181184

182185
privacyGradeMenu?.isVisible = viewState.showPrivacyGrade
183186
fireMenu?.isVisible = viewState.showFireButton
187+
popupMenu.contentView.backPopupMenuItem.isEnabled = viewState.browserShowing && webView.canGoBack()
188+
popupMenu.contentView.forwardPopupMenuItem.isEnabled = viewState.browserShowing && webView.canGoForward()
189+
popupMenu.contentView.refreshPopupMenuItem.isEnabled = viewState.browserShowing
190+
popupMenu.contentView.addBookmarksPopupMenuItem?.isEnabled = viewState.canAddBookmarks
184191

185192
when (viewState.showAutoCompleteSuggestions) {
186193
false -> autoCompleteSuggestionsList.gone()
@@ -211,7 +218,6 @@ class BrowserActivity : DuckDuckGoActivity() {
211218

212219
private fun configureToolbar() {
213220
setSupportActionBar(toolbar)
214-
215221
supportActionBar?.let {
216222
it.title = null
217223
}
@@ -262,7 +268,7 @@ class BrowserActivity : DuckDuckGoActivity() {
262268
webView.setDownloadListener { url, userAgent, contentDisposition, mimetype, contentLength ->
263269
val request = DownloadManager.Request(Uri.parse(url))
264270
request.allowScanningByMediaScanner()
265-
request.setNotificationVisibility(VISIBILITY_VISIBLE_NOTIFY_COMPLETED )
271+
request.setNotificationVisibility(VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
266272
val manager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
267273
manager.enqueue(request)
268274
Toast.makeText(applicationContext, getString(R.string.webviewDownload), Toast.LENGTH_LONG).show()
@@ -306,8 +312,6 @@ class BrowserActivity : DuckDuckGoActivity() {
306312

307313
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
308314
menuInflater.inflate(R.menu.menu_browser_activity, menu)
309-
addBookmarkMenuItem = menu?.findItem(R.id.add_bookmark_menu_item)
310-
addBookmarkMenuItem?.setEnabled(false)
311315
return true
312316
}
313317

@@ -321,50 +325,13 @@ class BrowserActivity : DuckDuckGoActivity() {
321325
launchFire()
322326
return true
323327
}
324-
R.id.refresh_menu_item -> {
325-
webView.reload()
326-
return true
327-
}
328-
R.id.back_menu_item -> {
329-
webView.goBack()
330-
return true
331-
}
332-
R.id.forward_menu_item -> {
333-
webView.goForward()
334-
return true
335-
}
336-
R.id.add_bookmark_menu_item -> {
337-
addBookmark()
338-
return true
339-
}
340-
R.id.bookmarks_menu_item -> {
341-
launchBookmarksView()
342-
return true
343-
}
344-
R.id.settings_menu_item -> {
345-
launchSettingsView()
346-
return true
328+
R.id.browser_popup_menu_item -> {
329+
launchPopupMenu()
347330
}
348331
}
349332
return false
350333
}
351334

352-
private fun addBookmark() {
353-
val title = webView.title
354-
val url = webView.url
355-
doAsync {
356-
viewModel.addBookmark(title, url)
357-
uiThread {
358-
toast(R.string.bookmarkAddedFeedback)
359-
}
360-
}
361-
}
362-
363-
private fun finishActivityAnimated() {
364-
clearViewPriorToAnimation()
365-
supportFinishAfterTransition()
366-
}
367-
368335
private fun launchPrivacyDashboard() {
369336
startActivityForResult(PrivacyDashboardActivity.intent(this), DASHBOARD_REQUEST_CODE)
370337
}
@@ -377,6 +344,52 @@ class BrowserActivity : DuckDuckGoActivity() {
377344
}).show()
378345
}
379346

347+
private fun launchPopupMenu() {
348+
val anchorView = findViewById<View>(R.id.browser_popup_menu_item)
349+
popupMenu.show(rootView, anchorView)
350+
}
351+
352+
fun onGoForwardClicked(view: View) {
353+
webView.goForward()
354+
popupMenu.dismiss()
355+
}
356+
357+
fun onGoBackClicked(view: View) {
358+
webView.goBack()
359+
popupMenu.dismiss()
360+
}
361+
362+
fun onRefreshClicked(view: View) {
363+
webView.reload()
364+
popupMenu.dismiss()
365+
}
366+
367+
fun onBookmarksClicked(view: View) {
368+
launchBookmarksView()
369+
popupMenu.dismiss()
370+
}
371+
372+
fun onAddBookmarkClicked(view: View) {
373+
addBookmark()
374+
popupMenu.dismiss()
375+
}
376+
377+
fun onSettingsClicked(view: View) {
378+
launchSettingsView()
379+
popupMenu.dismiss()
380+
}
381+
382+
private fun addBookmark() {
383+
val title = webView.title
384+
val url = webView.url
385+
doAsync {
386+
viewModel.addBookmark(title, url)
387+
uiThread {
388+
toast(R.string.bookmarkAddedFeedback)
389+
}
390+
}
391+
}
392+
380393
private fun launchSettingsView() {
381394
startActivityForResult(SettingsActivity.intent(this), SETTINGS_REQUEST_CODE)
382395
}
@@ -403,6 +416,11 @@ class BrowserActivity : DuckDuckGoActivity() {
403416
super.onBackPressed()
404417
}
405418

419+
private fun finishActivityAnimated() {
420+
clearViewPriorToAnimation()
421+
supportFinishAfterTransition()
422+
}
423+
406424
private fun clearViewPriorToAnimation() {
407425
acceptingRenderUpdates = false
408426
omnibarTextInput.text.clear()
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2018 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.app.browser
18+
19+
import android.graphics.Color
20+
import android.graphics.drawable.ColorDrawable
21+
import android.os.Build.VERSION.SDK_INT
22+
import android.view.Gravity
23+
import android.view.LayoutInflater
24+
import android.view.View
25+
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
26+
import android.widget.PopupWindow
27+
28+
class BrowserPopupMenu : PopupWindow {
29+
30+
constructor(layoutInflater: LayoutInflater, view: View = BrowserPopupMenu.inflate(layoutInflater))
31+
: super(view, WRAP_CONTENT, WRAP_CONTENT, true) {
32+
33+
if (SDK_INT <= 21) {
34+
// popupwindow gets stuck on the screen on API 21 without a background color.
35+
// Adding it however garbles the elevation so we cannot have elevation here
36+
setBackgroundDrawable(ColorDrawable(Color.WHITE))
37+
} else {
38+
elevation = 6.toFloat()
39+
}
40+
41+
animationStyle = android.R.style.Animation_Dialog
42+
}
43+
44+
fun show(rootView: View, anchorView: View) {
45+
val anchorLocation = IntArray(2)
46+
anchorView.getLocationOnScreen(anchorLocation)
47+
val x = margin
48+
val y = anchorLocation[1] + margin
49+
showAtLocation(rootView, Gravity.TOP or Gravity.END, x, y)
50+
}
51+
52+
companion object {
53+
54+
val margin = 30
55+
56+
fun inflate(layoutInflater: LayoutInflater): View {
57+
return layoutInflater.inflate(R.layout.popup_window_brower_menu, null)
58+
}
59+
60+
}
61+
}
62+

app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import com.duckduckgo.app.bookmarks.ui.BookmarksViewModel
2424
import com.duckduckgo.app.browser.BrowserViewModel
2525
import com.duckduckgo.app.browser.DuckDuckGoUrlDetector
2626
import com.duckduckgo.app.browser.omnibar.QueryUrlConverter
27-
import com.duckduckgo.app.global.db.AppDatabase
2827
import com.duckduckgo.app.onboarding.store.OnboardingStore
2928
import com.duckduckgo.app.onboarding.ui.OnboardingViewModel
3029
import com.duckduckgo.app.privacymonitor.db.NetworkLeaderboardDao
@@ -36,9 +35,8 @@ import com.duckduckgo.app.privacymonitor.ui.PrivacyPracticesViewModel
3635
import com.duckduckgo.app.privacymonitor.ui.ScorecardViewModel
3736
import com.duckduckgo.app.privacymonitor.ui.TrackerNetworksViewModel
3837
import com.duckduckgo.app.settings.SettingsViewModel
39-
import com.duckduckgo.app.settings.db.AppSettingsPreferencesStore
40-
import com.duckduckgo.app.settings.db.SettingsDataStore
4138
import com.duckduckgo.app.settings.db.AppConfigurationDao
39+
import com.duckduckgo.app.settings.db.SettingsDataStore
4240
import com.duckduckgo.app.trackerdetection.model.TrackerNetworks
4341
import javax.inject.Inject
4442

app/src/main/java/com/duckduckgo/app/home/HomeActivity.kt

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,29 @@ import android.support.v4.app.ActivityOptionsCompat
2323
import android.support.v7.app.AppCompatActivity
2424
import android.view.Menu
2525
import android.view.MenuItem
26+
import android.view.View
2627
import com.duckduckgo.app.about.AboutDuckDuckGoActivity
2728
import com.duckduckgo.app.bookmarks.ui.BookmarksActivity
2829
import com.duckduckgo.app.browser.BrowserActivity
30+
import com.duckduckgo.app.browser.BrowserPopupMenu
2931
import com.duckduckgo.app.browser.R
3032
import com.duckduckgo.app.global.intentText
3133
import com.duckduckgo.app.global.view.FireDialog
3234
import com.duckduckgo.app.settings.SettingsActivity
3335
import kotlinx.android.synthetic.main.activity_home.*
3436
import kotlinx.android.synthetic.main.content_home.*
37+
import kotlinx.android.synthetic.main.popup_window_brower_menu.view.*
3538
import org.jetbrains.anko.toast
3639

3740
class HomeActivity : AppCompatActivity() {
3841

42+
private lateinit var popupMenu: BrowserPopupMenu
43+
3944
override fun onCreate(savedInstanceState: Bundle?) {
4045
super.onCreate(savedInstanceState)
4146
setContentView(R.layout.activity_home)
4247
configureToolbar()
48+
configurePopupMenu()
4349

4450
searchInputBox.setOnClickListener { showSearchActivity() }
4551

@@ -53,6 +59,14 @@ class HomeActivity : AppCompatActivity() {
5359
supportActionBar?.setDisplayShowTitleEnabled(false)
5460
}
5561

62+
private fun configurePopupMenu() {
63+
popupMenu = BrowserPopupMenu(layoutInflater)
64+
popupMenu.contentView.backPopupMenuItem.isEnabled = false
65+
popupMenu.contentView.forwardPopupMenuItem.isEnabled = false
66+
popupMenu.contentView.refreshPopupMenuItem.isEnabled = false
67+
popupMenu.contentView.addBookmarksPopupMenuItem.isEnabled = false
68+
}
69+
5670
override fun onNewIntent(intent: Intent?) {
5771
super.onNewIntent(intent)
5872
consumeSharedText(intent)
@@ -77,18 +91,14 @@ class HomeActivity : AppCompatActivity() {
7791

7892
override fun onOptionsItemSelected(item: MenuItem): Boolean {
7993
return when (item.itemId) {
80-
R.id.settings_menu_item -> {
81-
startActivityForResult(SettingsActivity.intent(this), SETTINGS_REQUEST_CODE)
82-
true
83-
}
84-
R.id.bookmarks_menu_item -> {
85-
startActivityForResult(BookmarksActivity.intent(this), BOOKMARKS_REQUEST_CODE)
86-
true
87-
}
8894
R.id.fire_menu_item -> {
8995
launchFire()
9096
true
9197
}
98+
R.id.browser_popup_menu_item -> {
99+
launchPopupMenu()
100+
true
101+
}
92102
else -> return super.onOptionsItemSelected(item)
93103
}
94104
}
@@ -99,6 +109,21 @@ class HomeActivity : AppCompatActivity() {
99109
}).show()
100110
}
101111

112+
private fun launchPopupMenu() {
113+
val anchorView = findViewById(R.id.browser_popup_menu_item) as View
114+
popupMenu.show(rootView, anchorView)
115+
}
116+
117+
fun onBookmarksClicked(view: View) {
118+
startActivityForResult(BookmarksActivity.intent(this), BOOKMARKS_REQUEST_CODE)
119+
popupMenu.dismiss()
120+
}
121+
122+
fun onSettingsClicked(view: View) {
123+
startActivityForResult(SettingsActivity.intent(this), SETTINGS_REQUEST_CODE)
124+
popupMenu.dismiss()
125+
}
126+
102127
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
103128
when (requestCode) {
104129
SETTINGS_REQUEST_CODE -> onHandleSettingsResult(resultCode)
@@ -108,7 +133,7 @@ class HomeActivity : AppCompatActivity() {
108133
}
109134

110135
private fun onHandleBookmarksResult(resultCode: Int, data: Intent?) {
111-
when(resultCode) {
136+
when (resultCode) {
112137
BookmarksActivity.OPEN_URL_RESULT_CODE -> {
113138
openUrl(data?.action ?: return)
114139
}

app/src/main/java/com/duckduckgo/app/privacymonitor/ui/PrivacyDashboardActivity.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import android.content.Context
2222
import android.content.Intent
2323
import android.os.Bundle
2424
import android.support.v4.content.ContextCompat
25-
import android.view.MenuItem
2625
import android.view.View
2726
import com.duckduckgo.app.browser.R
2827
import com.duckduckgo.app.global.DuckDuckGoActivity

0 commit comments

Comments
 (0)