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

Commit

Permalink
Sign-out dialog (#2374)
Browse files Browse the repository at this point in the history
  • Loading branch information
keianhzo authored and MortimerGoro committed Nov 26, 2019
1 parent d3ce626 commit e6f5e2b
Show file tree
Hide file tree
Showing 17 changed files with 499 additions and 40 deletions.
47 changes: 46 additions & 1 deletion app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package org.mozilla.vrbrowser.browser

import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.os.Handler
import android.os.Looper
import android.util.Log
Expand All @@ -21,10 +23,16 @@ import mozilla.components.service.fxa.manager.SyncEnginesStorage
import mozilla.components.service.fxa.sync.SyncReason
import mozilla.components.service.fxa.sync.SyncStatusObserver
import mozilla.components.service.fxa.sync.getLastSynced
import org.mozilla.vrbrowser.R
import org.mozilla.vrbrowser.VRBrowserApplication
import org.mozilla.vrbrowser.utils.BitmapCache
import org.mozilla.vrbrowser.utils.SystemUtils
import org.mozilla.vrbrowser.utils.ViewUtils
import java.net.URL
import java.util.concurrent.CompletableFuture

const val PROFILE_PICTURE_TAG = "fxa_profile_picture"

class Accounts constructor(val context: Context) {

private val LOGTAG = SystemUtils.createLogtag(Accounts::class.java)
Expand All @@ -43,6 +51,7 @@ class Accounts constructor(val context: Context) {
NONE
}

var profilePicture: BitmapDrawable? = loadDefaultProfilePicture()
var loginOrigin: LoginOrigin = LoginOrigin.NONE
var accountStatus = AccountStatus.SIGNED_OUT
private val accountListeners = ArrayList<AccountObserver>()
Expand Down Expand Up @@ -152,6 +161,8 @@ class Accounts constructor(val context: Context) {
it.onLoggedOut()
}
}

loadDefaultProfilePicture()
}

override fun onProfileUpdated(profile: Profile) {
Expand All @@ -162,6 +173,8 @@ class Accounts constructor(val context: Context) {
it.onProfileUpdated(profile)
}
}

loadProfilePicture(profile)
}
}

Expand All @@ -183,6 +196,38 @@ class Accounts constructor(val context: Context) {
}
}

private fun loadProfilePicture(profile: Profile) {
CoroutineScope(Dispatchers.IO).launch {
try {
val url = URL(profile.avatar!!.url)
BitmapFactory.decodeStream(url.openStream())?.let {
val bitmap = ViewUtils.getRoundedCroppedBitmap(it)
profilePicture = BitmapDrawable(context.resources, bitmap)
BitmapCache.getInstance(context).addBitmap(PROFILE_PICTURE_TAG, bitmap)

} ?: throw IllegalArgumentException()

} catch (e: Exception) {
loadDefaultProfilePicture()

} finally {
accountListeners.toMutableList().forEach {
Handler(Looper.getMainLooper()).post {
it.onProfileUpdated(profile)
}
}
}
}
}

private fun loadDefaultProfilePicture(): BitmapDrawable? {
BitmapFactory.decodeResource(context.resources, R.drawable.ic_icon_settings_account)?.let {
BitmapCache.getInstance(context).addBitmap(PROFILE_PICTURE_TAG, it)
profilePicture = BitmapDrawable(context.resources, ViewUtils.getRoundedCroppedBitmap(it))
}

return profilePicture
}

fun addAccountListener(aListener: AccountObserver) {
if (!accountListeners.contains(aListener)) {
Expand Down Expand Up @@ -271,7 +316,7 @@ class Accounts constructor(val context: Context) {
return services.accountManager.accountProfile()
}

fun logoutAsync(): CompletableFuture<Unit?>? {
fun logoutAsync(): CompletableFuture<Unit?> {
otherDevices = emptyList()
return CoroutineScope(Dispatchers.Main).future {
services.accountManager.logoutAsync().await()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class BookmarksStore constructor(val context: Context) {
}

private val listeners = ArrayList<BookmarkListener>()
private val storage = (context.applicationContext as VRBrowserApplication).places.bookmarks
private var storage = (context.applicationContext as VRBrowserApplication).places.bookmarks
private val titles = rootTitles(context)
private val accountManager = (context.applicationContext as VRBrowserApplication).services.accountManager

Expand Down Expand Up @@ -100,6 +100,11 @@ class BookmarksStore constructor(val context: Context) {
listeners.clear()
}

internal fun updateStorage() {
storage = (context.applicationContext as VRBrowserApplication).places.bookmarks
notifyListeners()
}

fun getBookmarks(guid: String): CompletableFuture<List<BookmarkNode>?> = GlobalScope.future {
when (guid) {
BookmarkRoot.Mobile.id -> {
Expand Down Expand Up @@ -157,9 +162,7 @@ class BookmarksStore constructor(val context: Context) {

fun getTree(guid: String, recursive: Boolean): CompletableFuture<List<BookmarkNode>?> = GlobalScope.future {
storage.getTree(guid, recursive)?.children
?.map {
it.copy(title = titles[it.guid])
}
?.map { it.copy(title = titles[it.guid]) }
}

fun searchBookmarks(query: String, limit: Int): CompletableFuture<List<BookmarkNode>> = GlobalScope.future {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class HistoryStore constructor(val context: Context) {
private val LOGTAG = SystemUtils.createLogtag(HistoryStore::class.java)

private var listeners = ArrayList<HistoryListener>()
private val storage = (context.applicationContext as VRBrowserApplication).places.history
private var storage = (context.applicationContext as VRBrowserApplication).places.history

// Bookmarks might have changed during sync, so notify our listeners.
private val syncStatusObserver = object : SyncStatusObserver {
Expand Down Expand Up @@ -61,6 +61,11 @@ class HistoryStore constructor(val context: Context) {
listeners.clear()
}

internal fun updateStorage() {
storage = (context.applicationContext as VRBrowserApplication).places.history
notifyListeners()
}

fun getHistory(): CompletableFuture<List<String>?> = GlobalScope.future {
storage.getVisited()
}
Expand Down
37 changes: 34 additions & 3 deletions app/src/common/shared/org/mozilla/vrbrowser/browser/Places.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,42 @@ package org.mozilla.vrbrowser.browser
import android.content.Context
import mozilla.components.browser.storage.sync.PlacesBookmarksStorage
import mozilla.components.browser.storage.sync.PlacesHistoryStorage
import mozilla.components.support.base.log.logger.Logger
import org.mozilla.vrbrowser.browser.engine.SessionStore
import org.mozilla.vrbrowser.utils.SystemUtils

/**
* Entry point for interacting with places-backed storage layers.
*/
class Places(context: Context) {
val bookmarks by lazy { PlacesBookmarksStorage(context) }
val history by lazy { PlacesHistoryStorage(context) }
class Places(var context: Context) {

private val LOGTAG = SystemUtils.createLogtag(Places::class.java)

var bookmarks = PlacesBookmarksStorage(context)
var history = PlacesHistoryStorage(context)

fun clear() {
val files = context.filesDir.listFiles { dir, name ->
name.matches("places\\.sqlite.*".toRegex())
}
for (file in files) {
if (!file.delete()) {
Logger(LOGTAG).debug("Can't remove " + file.absolutePath)
}
}

bookmarks.cleanup()
// We create a new storage, otherwise we would need to restart the app so it's created in the Application onCreate
bookmarks = PlacesBookmarksStorage(context)
// Update the storage in the proxy class
SessionStore.get().bookmarkStore.updateStorage()

// We are supposed to call this but it fails internally as apparently the PlacesStorage is common
// and it's already being cleaned after bookmarks.cleanup()
// history.cleanup()
// We create a new storage, otherwise we would need to restart the app so it's created in the Application onCreate
history = PlacesHistoryStorage(context)
// Update the storage in the proxy class
SessionStore.get().historyStore.updateStorage()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import mozilla.appservices.Megazord
import mozilla.components.concept.sync.*
import mozilla.components.lib.fetch.httpurlconnection.HttpURLConnectionClient
import mozilla.components.service.fxa.*
import mozilla.components.service.fxa.manager.FxaAccountManager
import mozilla.components.service.fxa.sync.GlobalSyncableStoreProvider
Expand All @@ -32,8 +31,13 @@ import org.mozilla.vrbrowser.R
import org.mozilla.vrbrowser.browser.engine.EngineProvider
import org.mozilla.vrbrowser.browser.engine.GeckoViewFetchClient
import org.mozilla.vrbrowser.browser.engine.SessionStore
import org.mozilla.vrbrowser.utils.SystemUtils


class Services(val context: Context, places: Places): GeckoSession.NavigationDelegate {

private val LOGTAG = SystemUtils.createLogtag(Services::class.java)

class Services(context: Context, places: Places): GeckoSession.NavigationDelegate {
companion object {
const val CLIENT_ID = "7ad9917f6c55fb77"
const val REDIRECT_URL = "https://accounts.firefox.com/oauth/success/$CLIENT_ID"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ private static List<Bookmark> getDisplayListTree(@NonNull List<BookmarkNode> boo
for (BookmarkNode node : bookmarkNodes) {
if (node.getType() == BookmarkNodeType.FOLDER) {
if (openFolderGuid != null && openFolderGuid.contains(node.getGuid())) {
Bookmark bookmark = new Bookmark(node, level, true);
boolean canExpand = node.getChildren() != null && !node.getChildren().isEmpty();
Bookmark bookmark = new Bookmark(node, level, canExpand);
children.add(bookmark);
if (node.getChildren() != null) {
children.addAll(getDisplayListTree(node.getChildren(), level + 1, openFolderGuid));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
import mozilla.components.service.fxa.sync.SyncReason;
import mozilla.components.service.fxa.sync.SyncStatusObserver;

import static org.mozilla.vrbrowser.browser.BookmarksStoreKt.DESKTOP_ROOT;

public class BookmarksView extends FrameLayout implements BookmarksStore.BookmarkListener {

private static final String LOGTAG = SystemUtils.createLogtag(BookmarksView.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.vrbrowser.ui.widgets.dialogs;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.ViewTreeObserver;

import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.databinding.DataBindingUtil;

import org.mozilla.vrbrowser.R;
import org.mozilla.vrbrowser.databinding.CheckboxDialogBinding;
import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate;
import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement;

public class CheckboxDialogWidget extends UIDialog {

public interface Delegate {
void onButtonClicked(int index);
default void onDismiss() {}
}

public static final int NEGATIVE = 0;
public static final int POSITIVE = 1;

protected CheckboxDialogBinding mBinding;
private Delegate mAppDialogDelegate;

public CheckboxDialogWidget(Context aContext) {
super(aContext);
initialize(aContext);
}

protected void initialize(Context aContext) {
LayoutInflater inflater = LayoutInflater.from(aContext);

// Inflate this data binding layout
mBinding = DataBindingUtil.inflate(inflater, R.layout.checkbox_dialog, this, true);

mBinding.leftButton.setOnClickListener(v -> {
if (mAppDialogDelegate != null) {
mAppDialogDelegate.onButtonClicked(NEGATIVE);
}
});
mBinding.rightButton.setOnClickListener(v -> {
if (mAppDialogDelegate != null) {
mAppDialogDelegate.onButtonClicked(POSITIVE);
}
});
}

@Override
protected void initializeWidgetPlacement(WidgetPlacement aPlacement) {
aPlacement.visible = false;
aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.checkbox_dialog_width);
aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.checkbox_dialog_height);
aPlacement.parentAnchorX = 0.5f;
aPlacement.parentAnchorY = 0.5f;
aPlacement.anchorX = 0.5f;
aPlacement.anchorY = 0.5f;
aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_z_distance);
}

@Override
public void show(@ShowFlags int aShowFlags) {
measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
super.show(aShowFlags);

mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_DIM_BRIGHTNESS);

ViewTreeObserver viewTreeObserver = getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
mWidgetPlacement.height = (int)(getHeight()/mWidgetPlacement.density);
mWidgetManager.updateWidget(CheckboxDialogWidget.this);
}
});
}
}

public void hide(@HideFlags int aHideFlags) {
super.hide(aHideFlags);
mWidgetManager.popWorldBrightness(this);
}

public void setButtonsDelegate(Delegate delegate) {
mAppDialogDelegate = delegate;
}

public void setIcon(Drawable icon) {
mBinding.icon.setImageDrawable(icon);
}

public void setIcon(@DrawableRes int icon) {
mBinding.icon.setImageResource(icon);
}

public void setTitle(@StringRes int title) {
mBinding.title.setText(title);
}

public void setTitle(String title) {
mBinding.title.setText(title);
}

public void setBody(String body) {
mBinding.body.setText(body);
}

public void setBody(@StringRes int title) {
mBinding.body.setText(title);
}

public void setCheckboxText(@StringRes int text) {
mBinding.checkbox.setText(text);
}

public void setCheckboxText(String text) {
mBinding.checkbox.setText(text);
}

public void setButtons(@NonNull @StringRes int[] buttons) {
if (buttons.length > 0) {
mBinding.leftButton.setText(buttons[NEGATIVE]);
}
if (buttons.length > 1) {
mBinding.rightButton.setText(buttons[POSITIVE]);
}
}

public void setButtons(@NonNull String[] buttons) {
if (buttons.length > 0) {
mBinding.leftButton.setText(buttons[NEGATIVE]);
}
if (buttons.length > 1) {
mBinding.rightButton.setText(buttons[POSITIVE]);
}
}

public boolean isChecked() {
return mBinding.checkbox.isChecked();
}

}
Loading

0 comments on commit e6f5e2b

Please sign in to comment.