TunnelDetailFragment now restores state correctly after process death
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
62d8beff96
commit
9652fe99df
@ -13,7 +13,6 @@ import android.support.annotation.Nullable;
|
|||||||
|
|
||||||
import com.wireguard.android.Application;
|
import com.wireguard.android.Application;
|
||||||
import com.wireguard.android.model.Tunnel;
|
import com.wireguard.android.model.Tunnel;
|
||||||
import com.wireguard.android.model.TunnelManager;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -39,15 +38,17 @@ public abstract class BaseActivity extends ThemeChangeAwareActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
// Restore the saved tunnel if there is one; otherwise grab it from the arguments.
|
// Restore the saved tunnel if there is one; otherwise grab it from the arguments.
|
||||||
String savedTunnelName = null;
|
final String savedTunnelName;
|
||||||
if (savedInstanceState != null)
|
if (savedInstanceState != null)
|
||||||
savedTunnelName = savedInstanceState.getString(KEY_SELECTED_TUNNEL);
|
savedTunnelName = savedInstanceState.getString(KEY_SELECTED_TUNNEL);
|
||||||
else if (getIntent() != null)
|
else if (getIntent() != null)
|
||||||
savedTunnelName = getIntent().getStringExtra(KEY_SELECTED_TUNNEL);
|
savedTunnelName = getIntent().getStringExtra(KEY_SELECTED_TUNNEL);
|
||||||
if (savedTunnelName != null) {
|
else
|
||||||
final TunnelManager tunnelManager = Application.getTunnelManager();
|
savedTunnelName = null;
|
||||||
selectedTunnel = tunnelManager.getTunnels().get(savedTunnelName);
|
|
||||||
}
|
if (savedTunnelName != null)
|
||||||
|
Application.getTunnelManager().getTunnels()
|
||||||
|
.thenAccept(tunnels -> setSelectedTunnel(tunnels.get(savedTunnelName)));
|
||||||
|
|
||||||
// The selected tunnel must be set before the superclass method recreates fragments.
|
// The selected tunnel must be set before the superclass method recreates fragments.
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
@ -240,10 +240,13 @@ public final class GoBackend implements Backend {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
for (final Tunnel tunnel : Application.getTunnelManager().getTunnels()) {
|
Application.getTunnelManager().getTunnels().thenAccept(tunnels -> {
|
||||||
|
for (final Tunnel tunnel : tunnels) {
|
||||||
if (tunnel != null && tunnel.getState() != State.DOWN)
|
if (tunnel != null && tunnel.getState() != State.DOWN)
|
||||||
tunnel.setState(State.DOWN);
|
tunnel.setState(State.DOWN);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
vpnService = vpnService.newIncompleteFuture();
|
vpnService = vpnService.newIncompleteFuture();
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
@ -313,7 +313,7 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.setFragment(this);
|
binding.setFragment(this);
|
||||||
binding.setTunnels(Application.getTunnelManager().getTunnels());
|
Application.getTunnelManager().getTunnels().thenAccept(binding::setTunnels);
|
||||||
binding.setRowConfigurationHandler((ObservableKeyedRecyclerViewAdapter.RowConfigurationHandler<TunnelListItemBinding, Tunnel>) (binding, tunnel, position) -> {
|
binding.setRowConfigurationHandler((ObservableKeyedRecyclerViewAdapter.RowConfigurationHandler<TunnelListItemBinding, Tunnel>) (binding, tunnel, position) -> {
|
||||||
binding.setFragment(this);
|
binding.setFragment(this);
|
||||||
binding.getRoot().setOnClickListener(clicked -> {
|
binding.getRoot().setOnClickListener(clicked -> {
|
||||||
@ -341,10 +341,11 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
|
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_action_delete:
|
case R.id.menu_action_delete:
|
||||||
|
final Iterable<Integer> copyCheckedItems = new HashSet<>(checkedItems);
|
||||||
|
Application.getTunnelManager().getTunnels().thenAccept(tunnels -> {
|
||||||
final Collection<Tunnel> tunnelsToDelete = new ArrayList<>();
|
final Collection<Tunnel> tunnelsToDelete = new ArrayList<>();
|
||||||
for (final Integer position : checkedItems) {
|
for (final Integer position : copyCheckedItems)
|
||||||
tunnelsToDelete.add(Application.getTunnelManager().getTunnels().get(position));
|
tunnelsToDelete.add(tunnels.get(position));
|
||||||
}
|
|
||||||
|
|
||||||
final CompletableFuture[] futures = StreamSupport.stream(tunnelsToDelete)
|
final CompletableFuture[] futures = StreamSupport.stream(tunnelsToDelete)
|
||||||
.map(Tunnel::delete)
|
.map(Tunnel::delete)
|
||||||
@ -353,13 +354,16 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
.thenApply(x -> futures.length)
|
.thenApply(x -> futures.length)
|
||||||
.whenComplete(TunnelListFragment.this::onTunnelDeletionFinished);
|
.whenComplete(TunnelListFragment.this::onTunnelDeletionFinished);
|
||||||
|
|
||||||
|
});
|
||||||
checkedItems.clear();
|
checkedItems.clear();
|
||||||
mode.finish();
|
mode.finish();
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_action_select_all:
|
case R.id.menu_action_select_all:
|
||||||
for (int i = 0; i < Application.getTunnelManager().getTunnels().size(); ++i) {
|
Application.getTunnelManager().getTunnels().thenAccept(tunnels -> {
|
||||||
|
for (int i = 0; i < tunnels.size(); ++i) {
|
||||||
setItemChecked(i, true);
|
setItemChecked(i, true);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -19,7 +19,6 @@ import com.wireguard.android.configStore.ConfigStore;
|
|||||||
import com.wireguard.android.model.Tunnel.State;
|
import com.wireguard.android.model.Tunnel.State;
|
||||||
import com.wireguard.android.model.Tunnel.Statistics;
|
import com.wireguard.android.model.Tunnel.Statistics;
|
||||||
import com.wireguard.android.util.ExceptionLoggers;
|
import com.wireguard.android.util.ExceptionLoggers;
|
||||||
import com.wireguard.android.util.ObservableKeyedList;
|
|
||||||
import com.wireguard.android.util.ObservableSortedKeyedArrayList;
|
import com.wireguard.android.util.ObservableSortedKeyedArrayList;
|
||||||
import com.wireguard.android.util.ObservableSortedKeyedList;
|
import com.wireguard.android.util.ObservableSortedKeyedList;
|
||||||
import com.wireguard.config.Config;
|
import com.wireguard.config.Config;
|
||||||
@ -47,6 +46,7 @@ public final class TunnelManager extends BaseObservable {
|
|||||||
private static final String KEY_RUNNING_TUNNELS = "enabled_configs";
|
private static final String KEY_RUNNING_TUNNELS = "enabled_configs";
|
||||||
|
|
||||||
private final ConfigStore configStore;
|
private final ConfigStore configStore;
|
||||||
|
private final CompletableFuture<ObservableSortedKeyedList<String, Tunnel>> completableTunnels = new CompletableFuture<>();
|
||||||
private final ObservableSortedKeyedList<String, Tunnel> tunnels = new ObservableSortedKeyedArrayList<>(COMPARATOR);
|
private final ObservableSortedKeyedList<String, Tunnel> tunnels = new ObservableSortedKeyedArrayList<>(COMPARATOR);
|
||||||
@Nullable private Tunnel lastUsedTunnel;
|
@Nullable private Tunnel lastUsedTunnel;
|
||||||
private boolean haveLoaded;
|
private boolean haveLoaded;
|
||||||
@ -121,8 +121,8 @@ public final class TunnelManager extends BaseObservable {
|
|||||||
.thenApply(tunnel::onStatisticsChanged);
|
.thenApply(tunnel::onStatisticsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableKeyedList<String, Tunnel> getTunnels() {
|
public CompletableFuture<ObservableSortedKeyedList<String, Tunnel>> getTunnels() {
|
||||||
return tunnels;
|
return completableTunnels;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
@ -152,6 +152,8 @@ public final class TunnelManager extends BaseObservable {
|
|||||||
f.completeExceptionally(t);
|
f.completeExceptionally(t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
completableTunnels.complete(tunnels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshTunnelStates() {
|
public void refreshTunnelStates() {
|
||||||
@ -285,10 +287,12 @@ public final class TunnelManager extends BaseObservable {
|
|||||||
final String tunnelName = intent.getStringExtra("tunnel");
|
final String tunnelName = intent.getStringExtra("tunnel");
|
||||||
if (tunnelName == null)
|
if (tunnelName == null)
|
||||||
return;
|
return;
|
||||||
final Tunnel tunnel = manager.getTunnels().get(tunnelName);
|
manager.getTunnels().thenAccept(tunnels -> {
|
||||||
|
final Tunnel tunnel = tunnels.get(tunnelName);
|
||||||
if (tunnel == null)
|
if (tunnel == null)
|
||||||
return;
|
return;
|
||||||
manager.setTunnelState(tunnel, state);
|
manager.setTunnelState(tunnel, state);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,10 @@ public class ZipExporterPreference extends Preference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void exportZip() {
|
private void exportZip() {
|
||||||
final List<Tunnel> tunnels = new ArrayList<>(Application.getTunnelManager().getTunnels());
|
Application.getTunnelManager().getTunnels().thenAccept(this::exportZip);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportZip(final List<Tunnel> tunnels) {
|
||||||
final List<CompletableFuture<Config>> futureConfigs = new ArrayList<>(tunnels.size());
|
final List<CompletableFuture<Config>> futureConfigs = new ArrayList<>(tunnels.size());
|
||||||
for (final Tunnel tunnel : tunnels)
|
for (final Tunnel tunnel : tunnels)
|
||||||
futureConfigs.add(tunnel.getConfigAsync().toCompletableFuture());
|
futureConfigs.add(tunnel.getConfigAsync().toCompletableFuture());
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package com.wireguard.util;
|
package com.wireguard.util;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -18,8 +20,10 @@ public interface KeyedList<K, E extends Keyed<? extends K>> extends List<E> {
|
|||||||
|
|
||||||
boolean containsKey(K key);
|
boolean containsKey(K key);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
E get(K key);
|
E get(K key);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
E getLast(K key);
|
E getLast(K key);
|
||||||
|
|
||||||
int indexOfKey(K key);
|
int indexOfKey(K key);
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package com.wireguard.util;
|
package com.wireguard.util;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -17,10 +19,12 @@ import java.util.Set;
|
|||||||
public interface SortedKeyedList<K, E extends Keyed<? extends K>> extends KeyedList<K, E> {
|
public interface SortedKeyedList<K, E extends Keyed<? extends K>> extends KeyedList<K, E> {
|
||||||
Comparator<? super K> comparator();
|
Comparator<? super K> comparator();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
K firstKey();
|
K firstKey();
|
||||||
|
|
||||||
Set<K> keySet();
|
Set<K> keySet();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
K lastKey();
|
K lastKey();
|
||||||
|
|
||||||
Collection<E> values();
|
Collection<E> values();
|
||||||
|
Loading…
Reference in New Issue
Block a user