mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-04 02:51:09 +01:00
Updates
Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
d33130c7d5
commit
1c625fbb27
@ -111,7 +111,7 @@ dependencies {
|
|||||||
implementation 'net.zetetic:android-database-sqlcipher:3.5.9'
|
implementation 'net.zetetic:android-database-sqlcipher:3.5.9'
|
||||||
annotationProcessor 'io.requery:requery-processor:1.5.0'
|
annotationProcessor 'io.requery:requery-processor:1.5.0'
|
||||||
|
|
||||||
compile 'org.parceler:parceler-api:1.1.9'
|
implementation 'org.parceler:parceler-api:1.1.9'
|
||||||
annotationProcessor 'org.parceler:parceler:1.1.9'
|
annotationProcessor 'org.parceler:parceler:1.1.9'
|
||||||
|
|
||||||
implementation 'net.orange-box.storebox:storebox-lib:1.4.0'
|
implementation 'net.orange-box.storebox:storebox-lib:1.4.0'
|
||||||
@ -122,14 +122,14 @@ dependencies {
|
|||||||
implementation 'com.jakewharton:butterknife:8.8.1'
|
implementation 'com.jakewharton:butterknife:8.8.1'
|
||||||
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
|
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
|
||||||
|
|
||||||
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
|
||||||
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
|
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
|
||||||
|
|
||||||
debugImplementation "javax.transaction:transaction-api:1.1-rev-1"
|
debugImplementation "javax.transaction:transaction-api:1.1-rev-1"
|
||||||
|
|
||||||
implementation 'com.github.HITGIF:TextFieldBoxes:1.4.1'
|
implementation 'com.github.HITGIF:TextFieldBoxes:1.4.3'
|
||||||
|
|
||||||
implementation 'eu.davidea:flexible-adapter:5.0.2'
|
implementation 'eu.davidea:flexible-adapter:5.0.3'
|
||||||
implementation 'eu.davidea:flexible-adapter-ui:1.0.0-b3'
|
implementation 'eu.davidea:flexible-adapter-ui:1.0.0-b3'
|
||||||
|
|
||||||
implementation 'com.github.bumptech.glide:glide:4.3.0'
|
implementation 'com.github.bumptech.glide:glide:4.3.0'
|
||||||
|
@ -55,6 +55,7 @@ import com.nextcloud.talk.events.PeerConnectionEvent;
|
|||||||
import com.nextcloud.talk.events.SessionDescriptionSendEvent;
|
import com.nextcloud.talk.events.SessionDescriptionSendEvent;
|
||||||
import com.nextcloud.talk.models.database.UserEntity;
|
import com.nextcloud.talk.models.database.UserEntity;
|
||||||
import com.nextcloud.talk.models.json.call.CallOverall;
|
import com.nextcloud.talk.models.json.call.CallOverall;
|
||||||
|
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall;
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall;
|
import com.nextcloud.talk.models.json.generic.GenericOverall;
|
||||||
import com.nextcloud.talk.models.json.rooms.Room;
|
import com.nextcloud.talk.models.json.rooms.Room;
|
||||||
import com.nextcloud.talk.models.json.rooms.RoomsOverall;
|
import com.nextcloud.talk.models.json.rooms.RoomsOverall;
|
||||||
@ -200,6 +201,8 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
private boolean videoOn = false;
|
private boolean videoOn = false;
|
||||||
private boolean audioOn = false;
|
private boolean audioOn = false;
|
||||||
|
|
||||||
|
private boolean isMultiSession = false;
|
||||||
|
|
||||||
private Handler handler = new Handler();
|
private Handler handler = new Handler();
|
||||||
|
|
||||||
private boolean isPTTActive = false;
|
private boolean isPTTActive = false;
|
||||||
@ -770,7 +773,7 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
joinRoomAndCall();
|
checkCapabilities();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -790,6 +793,41 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkCapabilities() {
|
||||||
|
ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
|
||||||
|
.subscribeOn(Schedulers.newThread())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(new Observer<CapabilitiesOverall>() {
|
||||||
|
@Override
|
||||||
|
public void onSubscribe(Disposable d) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNext(CapabilitiesOverall capabilitiesOverall) {
|
||||||
|
isMultiSession = capabilitiesOverall.getOcs().getData()
|
||||||
|
.getCapabilities().getSpreedCapability() != null &&
|
||||||
|
capabilitiesOverall.getOcs().getData()
|
||||||
|
.getCapabilities().getSpreedCapability()
|
||||||
|
.getFeatures() != null && capabilitiesOverall.getOcs().getData()
|
||||||
|
.getCapabilities().getSpreedCapability()
|
||||||
|
.getFeatures().contains("multi-room-users");
|
||||||
|
|
||||||
|
joinRoomAndCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable e) {
|
||||||
|
isMultiSession = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void joinRoomAndCall() {
|
private void joinRoomAndCall() {
|
||||||
if ("0".equals(callSession)) {
|
if ("0".equals(callSession)) {
|
||||||
ncApi.joinRoom(credentials, ApiUtils.getUrlForRoomParticipants(baseUrl, roomToken), null)
|
ncApi.joinRoom(credentials, ApiUtils.getUrlForRoomParticipants(baseUrl, roomToken), null)
|
||||||
@ -871,7 +909,11 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Start pulling signaling messages
|
// Start pulling signaling messages
|
||||||
ncApi.pullSignalingMessages(credentials, ApiUtils.getUrlForSignaling(baseUrl))
|
String urlToken = null;
|
||||||
|
if (isMultiSession) {
|
||||||
|
urlToken = roomToken;
|
||||||
|
}
|
||||||
|
ncApi.pullSignalingMessages(credentials, ApiUtils.getUrlForSignaling(baseUrl, urlToken))
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.repeatWhen(observable -> observable)
|
.repeatWhen(observable -> observable)
|
||||||
@ -1367,7 +1409,12 @@ public class CallActivity extends AppCompatActivity {
|
|||||||
String stringToSend = stringBuilder.toString();
|
String stringToSend = stringBuilder.toString();
|
||||||
strings.add(stringToSend);
|
strings.add(stringToSend);
|
||||||
|
|
||||||
ncApi.sendSignalingMessages(credentials, ApiUtils.getUrlForSignaling(baseUrl),
|
String urlToken = null;
|
||||||
|
if (isMultiSession) {
|
||||||
|
urlToken = roomToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncApi.sendSignalingMessages(credentials, ApiUtils.getUrlForSignaling(baseUrl, urlToken),
|
||||||
strings.toString())
|
strings.toString())
|
||||||
.retry(3)
|
.retry(3)
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
|
@ -59,6 +59,8 @@ public abstract class BaseController extends RefWatchingController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void cleanTempCertPreference() {
|
private void cleanTempCertPreference() {
|
||||||
|
NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
|
||||||
|
|
||||||
List<String> temporaryClassNames = new ArrayList<>();
|
List<String> temporaryClassNames = new ArrayList<>();
|
||||||
temporaryClassNames.add(ServerSelectionController.class.getName());
|
temporaryClassNames.add(ServerSelectionController.class.getName());
|
||||||
temporaryClassNames.add(AccountVerificationController.class.getName());
|
temporaryClassNames.add(AccountVerificationController.class.getName());
|
||||||
@ -72,7 +74,6 @@ public abstract class BaseController extends RefWatchingController {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onViewBound(@NonNull View view) {
|
protected void onViewBound(@NonNull View view) {
|
||||||
NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
|
|
||||||
super.onViewBound(view);
|
super.onViewBound(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* Nextcloud Talk application
|
* Nextcloud Talk application
|
||||||
*
|
*
|
||||||
* @author Mario Danic
|
* @author Mario Danic
|
||||||
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -28,7 +28,7 @@ import android.os.Bundle;
|
|||||||
import android.support.annotation.MenuRes;
|
import android.support.annotation.MenuRes;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.design.widget.BottomNavigationView;
|
import android.support.design.widget.BottomNavigationView;
|
||||||
import android.support.design.widget.CoordinatorLayout;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@ -43,8 +43,6 @@ import com.bluelinelabs.conductor.RouterTransaction;
|
|||||||
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler;
|
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler;
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.controllers.base.BaseController;
|
import com.nextcloud.talk.controllers.base.BaseController;
|
||||||
import com.nextcloud.talk.utils.BottomNavigationUtils;
|
|
||||||
import com.nextcloud.talk.utils.animations.ViewHidingBehaviourAnimation;
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleBuilder;
|
import com.nextcloud.talk.utils.bundle.BundleBuilder;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
@ -55,10 +53,9 @@ import butterknife.BindView;
|
|||||||
* The backstack of each {@link MenuItem} is switched out, in order to maintain a separate backstack
|
* The backstack of each {@link MenuItem} is switched out, in order to maintain a separate backstack
|
||||||
* for each {@link MenuItem} - even though that is against the Google Design Guidelines:
|
* for each {@link MenuItem} - even though that is against the Google Design Guidelines:
|
||||||
*
|
*
|
||||||
* @author chris6647@gmail.com
|
|
||||||
* @see <a
|
* @see <a
|
||||||
* href="https://material.io/guidelines/components/bottom-navigation.html#bottom-navigation-behavior">Material
|
* href="https://material.io/guidelines/components/bottom-navigation.html#bottom-navigation-behavior">Material
|
||||||
* Design Guidelines</a>
|
* Design Guidelines</a>
|
||||||
*
|
*
|
||||||
* Internally works similarly to {@link com.bluelinelabs.conductor.support.RouterPagerAdapter},
|
* Internally works similarly to {@link com.bluelinelabs.conductor.support.RouterPagerAdapter},
|
||||||
* in the sense that it keeps track of the currently active {@link MenuItem} and the paired
|
* in the sense that it keeps track of the currently active {@link MenuItem} and the paired
|
||||||
@ -67,18 +64,17 @@ import butterknife.BindView;
|
|||||||
* of the Child {@link Router}, and cache it, so we have it available when we navigate to
|
* of the Child {@link Router}, and cache it, so we have it available when we navigate to
|
||||||
* another {@link MenuItem} and can then restore the correct Child {@link Router}
|
* another {@link MenuItem} and can then restore the correct Child {@link Router}
|
||||||
* (and thus the entire backstack)
|
* (and thus the entire backstack)
|
||||||
|
*
|
||||||
|
* @author chris6647@gmail.com
|
||||||
*/
|
*/
|
||||||
public abstract class BottomNavigationController extends BaseController {
|
public abstract class BottomNavigationController extends BaseController {
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
public static final String TAG = "BottomNavigationContr";
|
||||||
public static final String TAG = "BottomNavigationController";
|
|
||||||
|
|
||||||
private static final String KEY_MENU_RESOURCE = "key_menu_resource";
|
private static final String KEY_MENU_RESOURCE = "key_menu_resource";
|
||||||
private static final String KEY_STATE_ROUTER_BUNDLES = "key_state_router_bundles";
|
private static final String KEY_STATE_ROUTER_BUNDLES = "key_state_router_bundles";
|
||||||
private static final String KEY_STATE_CURRENTLY_SELECTED_ID = "key_state_currently_selected_id";
|
private static final String KEY_STATE_CURRENTLY_SELECTED_ID = "key_state_currently_selected_id";
|
||||||
|
public static final int INVALID_INT = -1;
|
||||||
@BindView(R.id.bottom_navigation_root)
|
|
||||||
CoordinatorLayout bottomNavigationRoot;
|
|
||||||
|
|
||||||
@BindView(R.id.navigation)
|
@BindView(R.id.navigation)
|
||||||
BottomNavigationView bottomNavigationView;
|
BottomNavigationView bottomNavigationView;
|
||||||
@ -86,11 +82,9 @@ public abstract class BottomNavigationController extends BaseController {
|
|||||||
@BindView(R.id.bottom_navigation_controller_container)
|
@BindView(R.id.bottom_navigation_controller_container)
|
||||||
ChangeHandlerFrameLayout controllerContainer;
|
ChangeHandlerFrameLayout controllerContainer;
|
||||||
|
|
||||||
private int currentlySelectedItemId;
|
private int currentlySelectedItemId = BottomNavigationController.INVALID_INT;
|
||||||
|
|
||||||
private SparseArray<Bundle> routerSavedStateBundles;
|
private SparseArray<Bundle> routerSavedStateBundles;
|
||||||
private Bundle cachedSavedInstanceState;
|
|
||||||
private Router lastActiveChildRouter;
|
|
||||||
|
|
||||||
public BottomNavigationController(@MenuRes int menu) {
|
public BottomNavigationController(@MenuRes int menu) {
|
||||||
this(new BundleBuilder(new Bundle()).putInt(KEY_MENU_RESOURCE, menu).build());
|
this(new BundleBuilder(new Bundle()).putInt(KEY_MENU_RESOURCE, menu).build());
|
||||||
@ -100,17 +94,6 @@ public abstract class BottomNavigationController extends BaseController {
|
|||||||
super(args);
|
super(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an internally used name to identify the Child {@link Router}s
|
|
||||||
*
|
|
||||||
* @param viewId
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static String makeRouterName(int viewId, long id) {
|
|
||||||
return viewId + ":" + id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||||
@ -120,25 +103,35 @@ public abstract class BottomNavigationController extends BaseController {
|
|||||||
@Override
|
@Override
|
||||||
protected void onViewBound(@NonNull View view) {
|
protected void onViewBound(@NonNull View view) {
|
||||||
super.onViewBound(view);
|
super.onViewBound(view);
|
||||||
|
|
||||||
/* Setup the BottomNavigationView with the constructor supplied Menu resource */
|
/* Setup the BottomNavigationView with the constructor supplied Menu resource */
|
||||||
bottomNavigationView.inflateMenu(getMenuResource());
|
bottomNavigationView.inflateMenu(getMenuResource());
|
||||||
|
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||||
|
int nextItemId = item.getItemId();
|
||||||
|
if (currentlySelectedItemId != nextItemId) {
|
||||||
|
Router oldChildRouter = getChildRouter(currentlySelectedItemId);
|
||||||
|
save(oldChildRouter, currentlySelectedItemId);
|
||||||
|
destroyChildRouter(oldChildRouter);
|
||||||
|
|
||||||
bottomNavigationView.setOnNavigationItemSelectedListener(
|
configureRouter(getChildRouter(nextItemId), nextItemId);
|
||||||
item -> {
|
currentlySelectedItemId = nextItemId;
|
||||||
navigateTo(item.getItemId(), getControllerFor(item.getItemId()));
|
} else {
|
||||||
return true;
|
resetCurrentBackstack();
|
||||||
});
|
}
|
||||||
|
return true;
|
||||||
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) bottomNavigationView.getLayoutParams();
|
}
|
||||||
layoutParams.setBehavior(new ViewHidingBehaviourAnimation());
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAttach(@NonNull View view) {
|
protected void onAttach(@NonNull View view) {
|
||||||
super.onAttach(view);
|
super.onAttach(view);
|
||||||
|
/*
|
||||||
/* Fresh start, setup everything */
|
* Fresh start, setup everything.
|
||||||
|
* Must be done in onAttach to avoid artifacts if using multiple Activities,
|
||||||
|
* and in case of resuming the app (i.e. when the view is not created again)
|
||||||
|
*/
|
||||||
if (routerSavedStateBundles == null) {
|
if (routerSavedStateBundles == null) {
|
||||||
Menu menu = bottomNavigationView.getMenu();
|
Menu menu = bottomNavigationView.getMenu();
|
||||||
int menuSize = menu.size();
|
int menuSize = menu.size();
|
||||||
@ -165,9 +158,7 @@ public abstract class BottomNavigationController extends BaseController {
|
|||||||
* and onRestoreInstanceState is called before onViewBound,
|
* and onRestoreInstanceState is called before onViewBound,
|
||||||
* all we need to do is rebind.
|
* all we need to do is rebind.
|
||||||
*/
|
*/
|
||||||
Router childRouter = getChildRouter(currentlySelectedItemId);
|
getChildRouter(currentlySelectedItemId).rebindIfNeeded();
|
||||||
childRouter.rebindIfNeeded();
|
|
||||||
lastActiveChildRouter = childRouter;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,39 +169,34 @@ public abstract class BottomNavigationController extends BaseController {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected Router getChildRouter(int itemId) {
|
protected Router getChildRouter(int itemId) {
|
||||||
return getChildRouter(controllerContainer, makeRouterName(controllerContainer.getId(), itemId));
|
return getChildRouter(controllerContainer, "itemId:" + itemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Correctly configure the {@link Router} given the cached routerSavedState.
|
* Correctly configure the {@link Router} given the cached routerSavedState.
|
||||||
*
|
*
|
||||||
* @param childRouter {@link Router} to configure
|
* @param itemId {@link MenuItem} ID
|
||||||
* @param itemId {@link MenuItem} ID
|
|
||||||
* @return true if {@link Router} was restored
|
* @return true if {@link Router} was restored
|
||||||
*/
|
*/
|
||||||
private boolean configureRouter(@NonNull Router childRouter, int itemId) {
|
private void configureRouter(@NonNull Router childRouter, int itemId) {
|
||||||
lastActiveChildRouter = childRouter;
|
|
||||||
Bundle routerSavedState = routerSavedStateBundles.get(itemId);
|
|
||||||
if (routerSavedState != null && !routerSavedState.isEmpty()) {
|
|
||||||
childRouter.restoreInstanceState(routerSavedState);
|
|
||||||
childRouter.rebindIfNeeded();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!childRouter.hasRootController()) {
|
if (!childRouter.hasRootController()) {
|
||||||
childRouter.setRoot(RouterTransaction.with(getControllerFor(itemId)));
|
Bundle routerSavedState = routerSavedStateBundles.get(itemId);
|
||||||
|
if (routerSavedState != null && !routerSavedState.isEmpty()) {
|
||||||
|
childRouter.restoreInstanceState(routerSavedState);
|
||||||
|
routerSavedStateBundles.remove(itemId);
|
||||||
|
} else {
|
||||||
|
childRouter.setRoot(RouterTransaction.with(getControllerFor(itemId)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
childRouter.rebindIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the {@link Router}, and remove(/destroy) it.
|
* Remove the supplied {@link Router} as a child of this Controller.
|
||||||
*
|
*
|
||||||
* @param childRouter {@link Router} to destroy
|
* @param childRouter
|
||||||
* @param itemId {@link MenuItem} ID
|
|
||||||
*/
|
*/
|
||||||
protected void destroyChildRouter(@NonNull Router childRouter, int itemId) {
|
protected void destroyChildRouter(@NonNull Router childRouter) {
|
||||||
save(childRouter, itemId);
|
|
||||||
removeChildRouter(childRouter);
|
removeChildRouter(childRouter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,21 +205,30 @@ public abstract class BottomNavigationController extends BaseController {
|
|||||||
* BottomNavigationController#getControllerFor(int)}, using a {@link FadeChangeHandler}.
|
* BottomNavigationController#getControllerFor(int)}, using a {@link FadeChangeHandler}.
|
||||||
*/
|
*/
|
||||||
protected void resetCurrentBackstack() {
|
protected void resetCurrentBackstack() {
|
||||||
lastActiveChildRouter.setRoot(RouterTransaction.with(this.getControllerFor(currentlySelectedItemId))
|
if (currentlySelectedItemId != BottomNavigationController.INVALID_INT) {
|
||||||
.pushChangeHandler(new FadeChangeHandler())
|
destroyChildRouter(getChildRouter(currentlySelectedItemId));
|
||||||
.popChangeHandler(new FadeChangeHandler()));
|
routerSavedStateBundles.remove(currentlySelectedItemId);
|
||||||
|
/* Must get reference to newly recreated childRouter to avoid old view not being removed */
|
||||||
|
getChildRouter(currentlySelectedItemId).setRoot(
|
||||||
|
RouterTransaction.with(getControllerFor(currentlySelectedItemId))
|
||||||
|
.pushChangeHandler(new FadeChangeHandler(true)));
|
||||||
|
} else {
|
||||||
|
Log.w(TAG,
|
||||||
|
"Attempted to reset backstack on BottomNavigationController with currentlySelectedItemId=" +
|
||||||
|
currentlySelectedItemId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigate to the supplied {@link Controller}, while setting the menuItemId as selected on the
|
* Navigate to the supplied {@link Controller}, while setting the menuItemId as selected on the
|
||||||
* {@link BottomNavigationView}.
|
* {@link BottomNavigationView}.
|
||||||
*
|
*
|
||||||
* @param itemId {@link MenuItem} ID
|
* @param itemId {@link MenuItem} ID
|
||||||
* @param controller {@link Controller} matching the itemId
|
|
||||||
*/
|
*/
|
||||||
protected void navigateTo(int itemId, @NonNull Controller controller) {
|
protected void navigateTo(int itemId) {
|
||||||
if (currentlySelectedItemId != itemId) {
|
if (currentlySelectedItemId != itemId) {
|
||||||
destroyChildRouter(lastActiveChildRouter, currentlySelectedItemId);
|
destroyChildRouter(getChildRouter(currentlySelectedItemId));
|
||||||
|
routerSavedStateBundles.remove(currentlySelectedItemId);
|
||||||
|
|
||||||
/* Ensure correct Checked state based on new selection */
|
/* Ensure correct Checked state based on new selection */
|
||||||
Menu menu = bottomNavigationView.getMenu();
|
Menu menu = bottomNavigationView.getMenu();
|
||||||
@ -246,29 +241,8 @@ public abstract class BottomNavigationController extends BaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configureRouter(getChildRouter(itemId), itemId);
|
||||||
currentlySelectedItemId = itemId;
|
currentlySelectedItemId = itemId;
|
||||||
Router childRouter = getChildRouter(currentlySelectedItemId);
|
|
||||||
if (configureRouter(childRouter, currentlySelectedItemId)) {
|
|
||||||
/* Determine if a Controller of same class already exists in the backstack */
|
|
||||||
Controller backstackController;
|
|
||||||
int size = childRouter.getBackstackSize();
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
backstackController = childRouter.getBackstack().get(i).controller();
|
|
||||||
if (BottomNavigationUtils.equals(backstackController.getClass(), controller.getClass())) {
|
|
||||||
/* Match found at root - so just set new root */
|
|
||||||
if (i == size - 1) {
|
|
||||||
childRouter.setRoot(RouterTransaction.with(controller));
|
|
||||||
} else {
|
|
||||||
/* Match found at i - pop until we're at the matching Controller */
|
|
||||||
for (int j = size; j < i; j--) {
|
|
||||||
childRouter.popCurrentController();
|
|
||||||
}
|
|
||||||
/* Replace the existing matching Controller with the new */
|
|
||||||
childRouter.replaceTopController(RouterTransaction.with(controller));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
resetCurrentBackstack();
|
resetCurrentBackstack();
|
||||||
}
|
}
|
||||||
@ -276,70 +250,34 @@ public abstract class BottomNavigationController extends BaseController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the Child {@link Router} into a {@link Bundle} and caches that {@link Bundle}.
|
* Saves the Child {@link Router} into a {@link Bundle} and caches that {@link Bundle}.
|
||||||
|
* <p>
|
||||||
|
* Be cautious as this call causes the controller flag it needs reattach,
|
||||||
|
* so it should only be called just prior to destroying the router
|
||||||
*
|
*
|
||||||
* @param childRouter to call {@link Router#saveInstanceState(Bundle)} on
|
* @param itemId {@link MenuItem} ID
|
||||||
* @param itemId {@link MenuItem} ID
|
|
||||||
*/
|
*/
|
||||||
private void save(Router childRouter, int itemId) {
|
private void save(Router childRouter, int itemId) {
|
||||||
if (childRouter != null) {
|
Bundle routerBundle = new Bundle();
|
||||||
Bundle routerBundle = new Bundle();
|
childRouter.saveInstanceState(routerBundle);
|
||||||
childRouter.saveInstanceState(routerBundle);
|
routerSavedStateBundles.put(itemId, routerBundle);
|
||||||
routerSavedStateBundles.put(itemId, routerBundle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
|
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
|
||||||
routerSavedStateBundles = savedInstanceState.getSparseParcelableArray(KEY_STATE_ROUTER_BUNDLES);
|
routerSavedStateBundles = savedInstanceState.getSparseParcelableArray(KEY_STATE_ROUTER_BUNDLES);
|
||||||
currentlySelectedItemId = savedInstanceState.getInt(KEY_STATE_CURRENTLY_SELECTED_ID);
|
currentlySelectedItemId =
|
||||||
if (savedInstanceState.containsKey(KEY_STATE_ROUTER_BUNDLES)
|
savedInstanceState.getInt(KEY_STATE_CURRENTLY_SELECTED_ID, BottomNavigationController.INVALID_INT);
|
||||||
|| savedInstanceState.containsKey(KEY_STATE_CURRENTLY_SELECTED_ID)) {
|
|
||||||
cachedSavedInstanceState = savedInstanceState;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
if (lastActiveChildRouter == null && cachedSavedInstanceState != null) {
|
outState.putSparseParcelableArray(KEY_STATE_ROUTER_BUNDLES, routerSavedStateBundles);
|
||||||
/*
|
/*
|
||||||
* Here we assume that we're in a state
|
* For some reason the BottomNavigationView does not seem to correctly restore its
|
||||||
* where the BottomNavigationController itself is in the backstack,
|
* selectedId, even though the view appears with the correct state.
|
||||||
* it has been restored, and is now being saved again.
|
* So we keep track of it manually
|
||||||
* In this case, the BottomNavigationController won't ever have had onViewBound() called,
|
*/
|
||||||
* and thus won't have any views to setup the Child Routers with.
|
outState.putInt(KEY_STATE_CURRENTLY_SELECTED_ID, currentlySelectedItemId);
|
||||||
* In this case, we assume that we've previously had onSaveInstanceState() called
|
|
||||||
* on us successfully, and thus have a cachedSavedInstanceState to use.
|
|
||||||
*
|
|
||||||
* To replicate issue this solves:
|
|
||||||
* Navigate from BottomNavigationController to another controller not hosted in
|
|
||||||
* the childRouter, background the app
|
|
||||||
* (with developer setting "don't keep activities in memory" enabled on the device),
|
|
||||||
* open the app again, and background it once more, and open it again to see it crash.
|
|
||||||
*/
|
|
||||||
outState.putSparseParcelableArray(
|
|
||||||
KEY_STATE_ROUTER_BUNDLES,
|
|
||||||
cachedSavedInstanceState.getSparseParcelableArray(KEY_STATE_ROUTER_BUNDLES));
|
|
||||||
outState.putInt(
|
|
||||||
KEY_STATE_CURRENTLY_SELECTED_ID,
|
|
||||||
cachedSavedInstanceState.getInt(KEY_STATE_CURRENTLY_SELECTED_ID));
|
|
||||||
} else if (currentlySelectedItemId != 0) {
|
|
||||||
/*
|
|
||||||
* Only save state if we have a valid item selected.
|
|
||||||
*
|
|
||||||
* Otherwise we may be in a state where we are in a backstack, but have never been shown.
|
|
||||||
* I.e. if we are put in a synthesized backstack, we've never been shown any UI,
|
|
||||||
* and therefore have nothing to save.
|
|
||||||
*/
|
|
||||||
save(lastActiveChildRouter, currentlySelectedItemId);
|
|
||||||
outState.putSparseParcelableArray(KEY_STATE_ROUTER_BUNDLES, routerSavedStateBundles);
|
|
||||||
/*
|
|
||||||
* For some reason the BottomNavigationView does not seem to correctly restore its
|
|
||||||
* selectedId, even though the view appears with the correct state.
|
|
||||||
* So we keep track of it manually
|
|
||||||
*/
|
|
||||||
outState.putInt(KEY_STATE_CURRENTLY_SELECTED_ID, currentlySelectedItemId);
|
|
||||||
lastActiveChildRouter = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -348,7 +286,13 @@ public abstract class BottomNavigationController extends BaseController {
|
|||||||
* The childRouter should handleBack,
|
* The childRouter should handleBack,
|
||||||
* as this BottomNavigationController doesn't have a back step sensible to the user.
|
* as this BottomNavigationController doesn't have a back step sensible to the user.
|
||||||
*/
|
*/
|
||||||
return lastActiveChildRouter != null && lastActiveChildRouter.handleBack();
|
Router childRouter = getChildRouter(currentlySelectedItemId);
|
||||||
|
if (childRouter != null) {
|
||||||
|
return childRouter.handleBack();
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "handleBack called with getChildRouter(currentlySelectedItemId) == null.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,12 +126,17 @@ public class ApiUtils {
|
|||||||
return getUrlForCall(baseUrl, token) + "/ping";
|
return getUrlForCall(baseUrl, token) + "/ping";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrlForSignaling(String baseUrl) {
|
public static String getUrlForSignaling(String baseUrl, @Nullable String token) {
|
||||||
return baseUrl + ocsApiVersion + spreedApiVersion + "/signaling";
|
String signalingUrl = baseUrl + ocsApiVersion + spreedApiVersion + "/signaling";
|
||||||
|
if (token == null) {
|
||||||
|
return signalingUrl;
|
||||||
|
} else {
|
||||||
|
return signalingUrl + "/" + token;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrlForSignalingSettings(String baseUrl) {
|
public static String getUrlForSignalingSettings(String baseUrl) {
|
||||||
return getUrlForSignaling(baseUrl) + "/settings";
|
return getUrlForSignaling(baseUrl, null) + "/settings";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
kotlinVersion = '1.2.21'
|
kotlinVersion = '1.2.31'
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
Loading…
Reference in New Issue
Block a user