Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add interstitial search #719

Merged
merged 29 commits into from
Feb 27, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
165adc0
Update to latest tooling
subsymbolic Jan 30, 2020
b0a920c
Remove unused parameter
subsymbolic Jan 30, 2020
84cdb3a
Remove unneeded unwrapping as per lint warning
subsymbolic Jan 30, 2020
75ae65e
Remove duplicate data and presentation logic from AutoCompleteApi
subsymbolic Jan 30, 2020
3271174
Initial interstitial screen
subsymbolic Jan 30, 2020
b4365ba
Add app list to view
subsymbolic Feb 3, 2020
45676b3
Tidy up device lookup and move off main thread
subsymbolic Feb 9, 2020
ea4578c
Use mini logo for better sizing
subsymbolic Feb 9, 2020
2214715
Merge branch 'develop' into feature/mia/interstitial_search
subsymbolic Feb 9, 2020
36b1d4b
Add scrolling
subsymbolic Feb 9, 2020
026a68e
Add view state reset and tweak app label text size
subsymbolic Feb 9, 2020
12b22bc
Remove colon from system search text as per design feedback
subsymbolic Feb 17, 2020
3be73e3
Update layout to show shadow at the bottom of autocomplete
subsymbolic Feb 17, 2020
b9b06de
Enable "no suggestions" and ensure it doesn't flash up on the screen
subsymbolic Feb 17, 2020
7a6cf08
Fix scrolling
subsymbolic Feb 20, 2020
e545232
Improve app lookup speed by reducing package manager lookups
subsymbolic Feb 20, 2020
bda60f6
Remove additional dev logging
subsymbolic Feb 20, 2020
b0ddd90
Tweak scrolling further
subsymbolic Feb 21, 2020
b235b09
Switch to word prefix matching
subsymbolic Feb 21, 2020
61fe705
Small tidy ups, remove dev logging, add explanatory comment and cance…
subsymbolic Feb 21, 2020
fa43e94
Make dax launch DuckDuckGo
subsymbolic Feb 21, 2020
6864a0e
Merge branch 'develop' into feature/mia/interstitial_search
subsymbolic Feb 21, 2020
95284bb
Add pixels
subsymbolic Feb 21, 2020
96d672f
Merge branch 'develop' into feature/mia/interstitial_search
subsymbolic Feb 21, 2020
005e188
Unit tests
subsymbolic Feb 24, 2020
cbea4ca
Merge branch 'develop' into feature/mia/interstitial_search
subsymbolic Feb 24, 2020
12451af
Rename variables and methods for clarity
subsymbolic Feb 26, 2020
c1343bd
Store app icon to avoid duplicate lookups and show message when app n…
subsymbolic Feb 26, 2020
4353881
Lint
subsymbolic Feb 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Tidy up device lookup and move off main thread
  • Loading branch information
subsymbolic committed Feb 9, 2020
commit 45676b365c83a209553e96fd474f808bc6bbe977
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class DeviceAppSuggestionsAdapter(

override fun onBindViewHolder(holder: DeviceAppViewHolder, position: Int) {
val app = deviceApps[position]
holder.title.text = app.shortActivityName
holder.title.text = app.shortName
holder.root.setOnClickListener {
clickListener(app)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@
package com.duckduckgo.app.systemsearch

import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.ApplicationInfo.DisplayNameComparator
import android.content.pm.PackageManager
import timber.log.Timber
import java.util.*
import androidx.annotation.WorkerThread

data class DeviceApp(
val shortActivityName: String,
val fullActivityName: String,
val shortName: String,
val longName: String,
val packageName: String,
val launchIntent: Intent
)
Expand All @@ -33,49 +32,34 @@ class DeviceAppsLookup(private val packageManager: PackageManager) {

private val allApps by lazy { all() }

@WorkerThread
fun query(query: String): List<DeviceApp> {

if (query.isBlank()) return emptyList()

return allApps.filter {
it.shortActivityName.contains(query, ignoreCase = true)
it.shortName.contains(query, ignoreCase = true)
}
}

@WorkerThread
private fun all(): List<DeviceApp> {
val intent = Intent(Intent.ACTION_MAIN)
val resInfos = packageManager.queryIntentActivities(intent, 0)
val mainPackages = mutableSetOf<String>()
val appInfos = mutableListOf<ApplicationInfo>()

for (resInfo in resInfos) {
val packageName = resInfo.activityInfo.packageName
mainPackages.add(packageName)
}

for (packageName in mainPackages) {
appInfos.add(packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA))
}

Collections.sort(appInfos, ApplicationInfo.DisplayNameComparator(packageManager))
val mainIntent = Intent(Intent.ACTION_MAIN)
val mainActivities = packageManager.queryIntentActivities(mainIntent, 0)

Timber.i("Found ${appInfos.size} matching apps")
val appsInfo = mainActivities.map {
it.activityInfo.packageName
}.toSet().map {
packageManager.getApplicationInfo(it, PackageManager.GET_META_DATA)
}.sortedWith(DisplayNameComparator(packageManager))

val appsList: List<DeviceApp> = appInfos.map {
return appsInfo.map {
val shortName = packageManager.getApplicationLabel(it).toString()
val packageName = it.packageName
val fullActivityName = packageManager.getApplicationInfo(packageName, 0).className
val icon = it.icon
Timber.i("Short name: $shortName, package: $packageName, full activity name: $fullActivityName")

val launchIntent = packageManager.getLaunchIntentForPackage(packageName)
if (fullActivityName == null) return@map null
if (launchIntent == null) return@map null
return@map DeviceApp(shortName, fullActivityName, packageName, launchIntent)

val fullName = packageManager.getApplicationInfo(packageName, 0).className ?: return@map null
val launchIntent = packageManager.getLaunchIntentForPackage(packageName) ?: return@map null
return@map DeviceApp(shortName, fullName, packageName, launchIntent)
}.filterNotNull()

Timber.i("Found ${appsList.size} matching Activities")
return appsList
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ package com.duckduckgo.app.systemsearch
import android.content.Intent
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.duckduckgo.app.autocomplete.api.AutoCompleteApi
import com.duckduckgo.app.global.SingleLiveEvent
import com.jakewharton.rxrelay2.PublishRelay
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.util.concurrent.TimeUnit

Expand Down Expand Up @@ -76,8 +80,12 @@ class SystemSearchViewModel(
val trimmedQuery = query.trim()
if (trimmedQuery != currentViewState().queryText) {
viewState.value = currentViewState().copy(queryText = trimmedQuery)
updateAppResults(deviceAppsLookup.query(query))
autoCompletePublishSubject.accept(trimmedQuery)
viewModelScope.launch {
withContext(Dispatchers.IO) {
updateAppResults(deviceAppsLookup.query(query))
}
}
}
}

Expand All @@ -95,10 +103,7 @@ class SystemSearchViewModel(
val hasAllResults = autocompleteResults.isNotEmpty() && appResults.isNotEmpty()
val newSuggestions = if (hasAllResults) autocompleteResults.take(4) else autocompleteResults
val newApps = if (hasAllResults) appResults.take(4) else appResults
viewState.value = currentViewState().copy(
autocompleteResults = newSuggestions,
appResults = newApps
)
viewState.postValue(currentViewState().copy(autocompleteResults = newSuggestions, appResults = newApps))
}

fun userClearedQuery() {
Expand Down