Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Hamburger menu (#2071)
Browse files Browse the repository at this point in the history
* Hamburger menu

* Updated the menu icon tooltip

* Show sent tab notification after sending a tab

* Keep the devices list always synced

* Handle devices list when not signed it

* Override user agent for accounts.firefox.com

* Change UA string to Desktop mode

* Show a syncing text while devices are being refreshed

* Remove user agent override from json

* Add the FxA login url in a new tab

* Fixed rebase issues

* UA mode fixes

* Update the accounts icon

* Invalidated menu views after changing image drawable

* Review fixes
  • Loading branch information
keianhzo authored and MortimerGoro committed Oct 29, 2019
1 parent 751a846 commit ede1763
Show file tree
Hide file tree
Showing 80 changed files with 1,710 additions and 810 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ infer-out/
fastlane/

app/.externalNativeBuild
app/.cxx
openwnn/.externalNativeBuild

*.swp
Expand Down
3 changes: 3 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,9 @@ dependencies {
// TODO this should not be necessary at all, see Services.kt
implementation deps.work.runtime

// TODO this should not be necessary at all, see Services.kt
implementation deps.work.runtime

// Kotlin dependency
implementation deps.kotlin.stdlib
implementation deps.kotlin.coroutines
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
import org.mozilla.vrbrowser.ui.widgets.RootWidget;
import org.mozilla.vrbrowser.ui.widgets.TrayWidget;
import org.mozilla.vrbrowser.ui.widgets.UIWidget;
import org.mozilla.vrbrowser.ui.widgets.VideoProjectionMenuWidget;
import org.mozilla.vrbrowser.ui.widgets.menus.VideoProjectionMenuWidget;
import org.mozilla.vrbrowser.ui.widgets.Widget;
import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate;
import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement;
Expand Down Expand Up @@ -1402,6 +1402,11 @@ public void openNewTab(@NonNull String uri) {
mWindows.addBackgroundTab(mWindows.getFocusedWindow(), uri);
}

@Override
public void openNewTabForeground(@NonNull String uri) {
mWindows.addTab(mWindows.getFocusedWindow(), uri);
}

@Override
public WindowWidget getFocusedWindow() {
return mWindows.getFocusedWindow();
Expand Down
63 changes: 59 additions & 4 deletions app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ import androidx.lifecycle.ProcessLifecycleOwner
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.future.future
import mozilla.components.concept.sync.AccountObserver
import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
import kotlinx.coroutines.launch
import mozilla.components.concept.sync.*
import mozilla.components.service.fxa.SyncEngine
import mozilla.components.service.fxa.manager.SyncEnginesStorage
import mozilla.components.service.fxa.sync.SyncReason
Expand Down Expand Up @@ -49,7 +47,9 @@ class Accounts constructor(val context: Context) {
var accountStatus = AccountStatus.SIGNED_OUT
private val accountListeners = ArrayList<AccountObserver>()
private val syncListeners = ArrayList<SyncStatusObserver>()
private val deviceConstellationListeners = ArrayList<DeviceConstellationObserver>()
private val services = (context.applicationContext as VRBrowserApplication).services
private var otherDevices = emptyList<Device>()
private val syncStorage = SyncEnginesStorage(context)
var isSyncing = false

Expand Down Expand Up @@ -82,6 +82,17 @@ class Accounts constructor(val context: Context) {
}
}

private val deviceConstellationObserver = object : DeviceConstellationObserver {
override fun onDevicesUpdate(constellation: ConstellationState) {
otherDevices = constellation.otherDevices
deviceConstellationListeners.toMutableList().forEach {
Handler(Looper.getMainLooper()).post {
it.onDevicesUpdate(constellation)
}
}
}
}

private val accountObserver = object : AccountObserver {
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
accountStatus = AccountStatus.SIGNED_IN
Expand All @@ -91,6 +102,13 @@ class Accounts constructor(val context: Context) {
syncStorage.setStatus(SyncEngine.History, SettingsStore.getInstance(context).isHistorySyncEnabled)
services.accountManager.syncNowAsync(SyncReason.EngineChange, false)

// Update device list
account.deviceConstellation().registerDeviceObserver(
deviceConstellationObserver,
ProcessLifecycleOwner.get(),
true
)

account.deviceConstellation().refreshDevicesAsync()
accountListeners.toMutableList().forEach {
Handler(Looper.getMainLooper()).post {
Expand Down Expand Up @@ -173,6 +191,20 @@ class Accounts constructor(val context: Context) {
syncListeners.clear()
}

fun addDeviceConstellationListener(aListener: DeviceConstellationObserver) {
if (!deviceConstellationListeners.contains(aListener)) {
deviceConstellationListeners.add(aListener)
}
}

fun removeDeviceConstellationListener(aListener: DeviceConstellationObserver) {
deviceConstellationListeners.remove(aListener)
}

fun removeAllDeviceConstellationListeners() {
deviceConstellationListeners.clear()
}

fun authUrlAsync(): CompletableFuture<String?>? {
return CoroutineScope(Dispatchers.Main).future {
services.accountManager.beginAuthenticationAsync().await()
Expand Down Expand Up @@ -219,6 +251,7 @@ class Accounts constructor(val context: Context) {
}

fun logoutAsync(): CompletableFuture<Unit?>? {
otherDevices = emptyList()
return CoroutineScope(Dispatchers.Main).future {
services.accountManager.logoutAsync().await()
}
Expand Down Expand Up @@ -283,4 +316,26 @@ class Accounts constructor(val context: Context) {
return getLastSynced(context)
}

fun devicesByCapability(capabilities: List<DeviceCapability>): List<Device> {
return otherDevices.filter { it.capabilities.containsAll(capabilities) }
}

fun sendTabs(targetDevices: List<Device>, url: String, title: String) {
CoroutineScope(Dispatchers.Main).launch {
services.accountManager.authenticatedAccount()?.deviceConstellation()?.let { constellation ->
// Ignore devices that can't receive tabs or are not in the received list
val targets = constellation.state()?.otherDevices?.filter {
it.capabilities.contains(DeviceCapability.SEND_TAB)
targetDevices.contains(it)
}

targets?.forEach {
constellation.sendEventToDeviceAsync(
it.id, DeviceEventOutgoing.SendTab(title, url)
).await()
}
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ class BookmarksStore constructor(val context: Context) {
}
}

fun searchBookmarks(query: String, limit: Int): CompletableFuture<List<BookmarkNode>> = GlobalScope.future {
storage.searchBookmarks(query, limit)
}

private suspend fun getBookmarkByUrl(aURL: String): BookmarkNode? {
val bookmarks: List<BookmarkNode>? = storage.getBookmarksWithUrl(aURL)
if (bookmarks == null || bookmarks.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ import android.os.Looper
import androidx.lifecycle.ProcessLifecycleOwner
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.future.future
import mozilla.components.concept.storage.PageObservation
import mozilla.components.concept.storage.PageVisit
import mozilla.components.concept.storage.VisitInfo
import mozilla.components.concept.storage.VisitType
import mozilla.components.concept.storage.*
import mozilla.components.service.fxa.sync.SyncStatusObserver
import mozilla.components.support.base.log.logger.Logger
import org.mozilla.vrbrowser.VRBrowserApplication
Expand Down Expand Up @@ -126,6 +123,10 @@ class HistoryStore constructor(val context: Context) {
result.isNotEmpty() && result[0]
}

fun getSuggestions(query: String, limit: Int): CompletableFuture<List<SearchResult>> = GlobalScope.future {
storage.getSuggestions(query, limit)
}

private fun notifyListeners() {
if (listeners.size > 0) {
val listenersCopy = ArrayList(listeners)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ private void handlePopUpRequest(@NonNull PopUpRequest request) {
mPopUpPrompt.setButtonsDelegate(new BaseAppDialogWidget.Delegate() {
@Override
public void onButtonClicked(int index) {
boolean allowed = index != PopUpBlockDialogWidget.LEFT;
boolean allowed = index != PopUpBlockDialogWidget.NEGATIVE;
boolean askAgain = mPopUpPrompt.askAgain();
if (!askAgain) {
mAllowedPopUpSites.add(new PopUpSite(request.uri, allowed));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import mozilla.components.support.rustlog.RustLog
import org.mozilla.geckoview.AllowOrDeny
import org.mozilla.geckoview.GeckoResult
import org.mozilla.geckoview.GeckoSession
import org.mozilla.vrbrowser.browser.engine.SessionStore
import org.mozilla.vrbrowser.R
import org.mozilla.vrbrowser.browser.engine.SessionStore

class Services(context: Context, places: Places): GeckoSession.NavigationDelegate {
companion object {
Expand Down Expand Up @@ -83,15 +83,13 @@ class Services(context: Context, places: Places): GeckoSession.NavigationDelegat
}
}
}

val accountManager = FxaAccountManager(
context = context,
serverConfig = ServerConfig.release(CLIENT_ID, REDIRECT_URL),
deviceConfig = DeviceConfig(
// This is a default name, and can be changed once user is logged in.
// E.g. accountManager.authenticatedAccount()?.deviceConstellation()?.setDeviceNameAsync("new name")
name = "${context.getString(R.string.app_name)} on ${Build.MANUFACTURER} ${Build.MODEL}",
// TODO need a new device type! "VR"
type = DeviceType.VR,
capabilities = setOf(DeviceCapability.SEND_TAB)
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
import java.util.List;
import java.util.concurrent.CompletableFuture;

import mozilla.appservices.places.BookmarkRoot;

public class SuggestionsProvider {

private static final String LOGTAG = SuggestionsProvider.class.getSimpleName();
Expand All @@ -31,31 +29,27 @@ public int compare(Object obj1, Object obj2) {
return 0;

} else if (suggestion1.type == suggestion2.type) {
if (mFilterText != null) {
if (suggestion1.title != null && suggestion2.title != null) {
return suggestion1.title.toLowerCase().indexOf(mFilterText) - suggestion2.title.toLowerCase().indexOf(mFilterText);
if (suggestion1.type == Type.HISTORY) {
if (suggestion1.score != suggestion2.score) {
return suggestion1.score - suggestion2.score;
}
return suggestion1.url.toLowerCase().indexOf(mFilterText) - suggestion2.url.indexOf(mFilterText);

} else {
return suggestion1.url.compareTo(suggestion2.url);
}

return suggestion1.url.compareTo(suggestion2.url);

} else {
return suggestion1.type.ordinal() - suggestion2.type.ordinal();
}
}
}

private Context mContext;
private SearchEngineWrapper mSearchEngineWrapper;
private String mText;
private String mFilterText;
private Comparator mComparator;

public SuggestionsProvider(Context context) {
mContext = context;
mSearchEngineWrapper = SearchEngineWrapper.get(mContext);
mSearchEngineWrapper = SearchEngineWrapper.get(context);
mFilterText = "";
mComparator = new DefaultSuggestionsComparator();
}
Expand All @@ -81,16 +75,16 @@ public void setComparator(Comparator comparator) {

public CompletableFuture<List<SuggestionItem>> getBookmarkSuggestions(@NonNull List<SuggestionItem> items) {
CompletableFuture future = new CompletableFuture();
// Explicitly passing Root will look in all the bookmarks, default is just to look in the mobile bookmarks.
SessionStore.get().getBookmarkStore().getBookmarks(BookmarkRoot.Root.getId()).thenAcceptAsync((bookmarks) -> {
bookmarks.stream().
filter(b -> b.getUrl().toLowerCase().contains(mFilterText) ||
b.getTitle().toLowerCase().contains(mFilterText))
SessionStore.get().getBookmarkStore().searchBookmarks(mFilterText, 100).thenAcceptAsync((bookmarks) -> {
bookmarks.stream()
.filter((b) -> !b.getUrl().startsWith("place:") &&
!b.getUrl().startsWith("about:reader"))
.forEach(b -> items.add(SuggestionItem.create(
b.getTitle(),
b.getUrl(),
null,
Type.BOOKMARK
Type.BOOKMARK,
0
)));
if (mComparator != null) {
items.sort(mComparator);
Expand All @@ -108,15 +102,13 @@ public CompletableFuture<List<SuggestionItem>> getBookmarkSuggestions(@NonNull L

public CompletableFuture<List<SuggestionItem>> getHistorySuggestions(@NonNull final List<SuggestionItem> items) {
CompletableFuture future = new CompletableFuture();
SessionStore.get().getHistoryStore().getHistory().thenAcceptAsync((history) -> {
history.stream()
.filter(h ->
h.toLowerCase().contains(mFilterText))
.forEach(h -> items.add(SuggestionItem.create(
h,
h,
SessionStore.get().getHistoryStore().getSuggestions(mFilterText, 100).thenAcceptAsync((history) -> {
history.forEach(h -> items.add(SuggestionItem.create(
h.getTitle(),
h.getUrl(),
null,
Type.HISTORY
Type.HISTORY,
h.getScore()
)));
if (mComparator != null) {
items.sort(mComparator);
Expand All @@ -141,7 +133,8 @@ public CompletableFuture<List<SuggestionItem>> getSearchEngineSuggestions(@NonNu
mText,
getSearchURLOrDomain(mText),
null,
Type.COMPLETION
Type.COMPLETION,
0
));
}

Expand All @@ -150,7 +143,8 @@ public CompletableFuture<List<SuggestionItem>> getSearchEngineSuggestions(@NonNu
mFilterText,
getSearchURLOrDomain(mFilterText),
null,
Type.SUGGESTION
Type.SUGGESTION,
0
));

// Suggestions
Expand All @@ -161,7 +155,8 @@ public CompletableFuture<List<SuggestionItem>> getSearchEngineSuggestions(@NonNu
s,
url,
null,
Type.SUGGESTION
Type.SUGGESTION,
0
));
});
if (mComparator != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.DimenRes;
import androidx.annotation.Dimension;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.databinding.BindingAdapter;

import org.mozilla.vrbrowser.R;
import org.mozilla.vrbrowser.ui.views.HoneycombButton;
import org.mozilla.vrbrowser.ui.views.UIButton;

import java.text.SimpleDateFormat;
import java.util.Calendar;
Expand Down Expand Up @@ -111,4 +113,9 @@ public static void setFxALastSync(@NonNull TextView view, long lastSync) {
}



@BindingAdapter("android:layout_width")
public static void setLayoutWidth(@NonNull UIButton button, @NonNull @Dimension float dimen) {
button.setLayoutWidth(dimen);
}
}
Loading

0 comments on commit ede1763

Please sign in to comment.