mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 13:49:53 +01:00
Move transport toggles back to the settings screen.
This commit is contained in:
@@ -4,9 +4,12 @@ import android.content.Intent;
|
|||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.GridView;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@@ -17,6 +20,11 @@ import org.briarproject.bramble.api.db.DbException;
|
|||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.Plugin.State;
|
||||||
|
import org.briarproject.bramble.api.plugin.TorConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
@@ -29,16 +37,21 @@ import org.briarproject.briar.android.logout.SignOutFragment;
|
|||||||
import org.briarproject.briar.android.privategroup.list.GroupListFragment;
|
import org.briarproject.briar.android.privategroup.list.GroupListFragment;
|
||||||
import org.briarproject.briar.android.settings.SettingsActivity;
|
import org.briarproject.briar.android.settings.SettingsActivity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
@@ -53,6 +66,9 @@ import static androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE;
|
|||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
|
||||||
|
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
||||||
|
import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING;
|
||||||
|
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
|
||||||
import static org.briarproject.briar.android.BriarService.EXTRA_STARTUP_FAILED;
|
import static org.briarproject.briar.android.BriarService.EXTRA_STARTUP_FAILED;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD;
|
||||||
import static org.briarproject.briar.android.navdrawer.IntentRouter.handleExternalIntent;
|
import static org.briarproject.briar.android.navdrawer.IntentRouter.handleExternalIntent;
|
||||||
@@ -79,7 +95,8 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
public static Uri SIGN_OUT_URI =
|
public static Uri SIGN_OUT_URI =
|
||||||
Uri.parse("briar-content://org.briarproject.briar/sign-out");
|
Uri.parse("briar-content://org.briarproject.briar/sign-out");
|
||||||
|
|
||||||
private NavDrawerViewModel viewModel;
|
private NavDrawerViewModel navDrawerViewModel;
|
||||||
|
private PluginViewModel pluginViewModel;
|
||||||
private ActionBarDrawerToggle drawerToggle;
|
private ActionBarDrawerToggle drawerToggle;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -91,6 +108,9 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
private DrawerLayout drawerLayout;
|
private DrawerLayout drawerLayout;
|
||||||
private NavigationView navigation;
|
private NavigationView navigation;
|
||||||
|
|
||||||
|
private List<Transport> transports;
|
||||||
|
private BaseAdapter transportsAdapter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectActivity(ActivityComponent component) {
|
public void injectActivity(ActivityComponent component) {
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
@@ -102,20 +122,21 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
exitIfStartupFailed(getIntent());
|
exitIfStartupFailed(getIntent());
|
||||||
setContentView(R.layout.activity_nav_drawer);
|
setContentView(R.layout.activity_nav_drawer);
|
||||||
|
|
||||||
viewModel = ViewModelProviders.of(this, viewModelFactory)
|
ViewModelProvider provider =
|
||||||
.get(NavDrawerViewModel.class);
|
ViewModelProviders.of(this, viewModelFactory);
|
||||||
|
navDrawerViewModel = provider.get(NavDrawerViewModel.class);
|
||||||
|
pluginViewModel = provider.get(PluginViewModel.class);
|
||||||
|
|
||||||
viewModel.showExpiryWarning().observe(this, this::showExpiryWarning);
|
navDrawerViewModel.showExpiryWarning()
|
||||||
viewModel.shouldAskForDozeWhitelisting().observe(this, ask -> {
|
.observe(this, this::showExpiryWarning);
|
||||||
|
navDrawerViewModel.shouldAskForDozeWhitelisting().observe(this, ask -> {
|
||||||
if (ask) showDozeDialog(getString(R.string.setup_doze_intro));
|
if (ask) showDozeDialog(getString(R.string.setup_doze_intro));
|
||||||
});
|
});
|
||||||
|
|
||||||
View drawerScrollView = findViewById(R.id.drawerScrollView);
|
|
||||||
new PluginViewController(drawerScrollView, this, viewModel);
|
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
drawerLayout = findViewById(R.id.drawer_layout);
|
drawerLayout = findViewById(R.id.drawer_layout);
|
||||||
navigation = findViewById(R.id.navigation);
|
navigation = findViewById(R.id.navigation);
|
||||||
|
GridView transportsView = findViewById(R.id.transportsView);
|
||||||
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
ActionBar actionBar = requireNonNull(getSupportActionBar());
|
ActionBar actionBar = requireNonNull(getSupportActionBar());
|
||||||
@@ -128,6 +149,9 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
drawerLayout.addDrawerListener(drawerToggle);
|
drawerLayout.addDrawerListener(drawerToggle);
|
||||||
navigation.setNavigationItemSelectedListener(this);
|
navigation.setNavigationItemSelectedListener(this);
|
||||||
|
|
||||||
|
initializeTransports();
|
||||||
|
transportsView.setAdapter(transportsAdapter);
|
||||||
|
|
||||||
lockManager.isLockable().observe(this, this::setLockVisible);
|
lockManager.isLockable().observe(this, this::setLockVisible);
|
||||||
|
|
||||||
if (lifecycleManager.getLifecycleState().isAfter(RUNNING)) {
|
if (lifecycleManager.getLifecycleState().isAfter(RUNNING)) {
|
||||||
@@ -146,7 +170,7 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
lockManager.checkIfLockable();
|
lockManager.checkIfLockable();
|
||||||
viewModel.checkExpiryWarning();
|
navDrawerViewModel.checkExpiryWarning();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -154,7 +178,7 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
@Nullable Intent data) {
|
@Nullable Intent data) {
|
||||||
super.onActivityResult(request, result, data);
|
super.onActivityResult(request, result, data);
|
||||||
if (request == REQUEST_PASSWORD && result == RESULT_OK) {
|
if (request == REQUEST_PASSWORD && result == RESULT_OK) {
|
||||||
viewModel.checkDozeWhitelisting();
|
navDrawerViewModel.checkDozeWhitelisting();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,11 +367,101 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
ImageView expiryWarningClose =
|
ImageView expiryWarningClose =
|
||||||
expiryWarning.findViewById(R.id.expiryWarningClose);
|
expiryWarning.findViewById(R.id.expiryWarningClose);
|
||||||
expiryWarningClose.setOnClickListener(v ->
|
expiryWarningClose.setOnClickListener(v ->
|
||||||
viewModel.expiryWarningDismissed()
|
navDrawerViewModel.expiryWarningDismissed());
|
||||||
);
|
|
||||||
expiryWarning.setVisibility(VISIBLE);
|
expiryWarning.setVisibility(VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
expiryWarning.setVisibility(GONE);
|
expiryWarning.setVisibility(GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeTransports() {
|
||||||
|
transports = new ArrayList<>(3);
|
||||||
|
|
||||||
|
transportsAdapter = new BaseAdapter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return transports.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Transport getItem(int position) {
|
||||||
|
return transports.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView,
|
||||||
|
ViewGroup parent) {
|
||||||
|
View view;
|
||||||
|
if (convertView != null) {
|
||||||
|
view = convertView;
|
||||||
|
} else {
|
||||||
|
LayoutInflater inflater = getLayoutInflater();
|
||||||
|
view = inflater.inflate(R.layout.list_item_transport,
|
||||||
|
parent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transport t = getItem(position);
|
||||||
|
|
||||||
|
ImageView icon = view.findViewById(R.id.imageView);
|
||||||
|
icon.setImageDrawable(ContextCompat
|
||||||
|
.getDrawable(NavDrawerActivity.this, t.iconId));
|
||||||
|
icon.setColorFilter(getIconColour(t.state));
|
||||||
|
|
||||||
|
TextView text = view.findViewById(R.id.textView);
|
||||||
|
text.setText(getString(t.textId));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
transports.add(createTransport(TorConstants.ID,
|
||||||
|
R.drawable.transport_tor, R.string.transport_tor));
|
||||||
|
transports.add(createTransport(LanTcpConstants.ID,
|
||||||
|
R.drawable.transport_lan, R.string.transport_lan));
|
||||||
|
transports.add(createTransport(BluetoothConstants.ID,
|
||||||
|
R.drawable.transport_bt, R.string.transport_bt));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIconColour(State state) {
|
||||||
|
int colorRes;
|
||||||
|
if (state == ACTIVE) {
|
||||||
|
colorRes = R.color.briar_green_light;
|
||||||
|
} else if (state == ENABLING) {
|
||||||
|
colorRes = R.color.briar_yellow;
|
||||||
|
} else {
|
||||||
|
colorRes = android.R.color.tertiary_text_light;
|
||||||
|
}
|
||||||
|
return ContextCompat.getColor(this, colorRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Transport createTransport(TransportId id, @DrawableRes int iconId,
|
||||||
|
@StringRes int textId) {
|
||||||
|
Transport transport = new Transport(iconId, textId);
|
||||||
|
pluginViewModel.getPluginState(id).observe(this, state -> {
|
||||||
|
transport.state = state;
|
||||||
|
transportsAdapter.notifyDataSetChanged();
|
||||||
|
});
|
||||||
|
return transport;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Transport {
|
||||||
|
|
||||||
|
@DrawableRes
|
||||||
|
private final int iconId;
|
||||||
|
@StringRes
|
||||||
|
private final int textId;
|
||||||
|
|
||||||
|
private State state = STARTING_STOPPING;
|
||||||
|
|
||||||
|
private Transport(@DrawableRes int iconId, @StringRes int textId) {
|
||||||
|
this.iconId = iconId;
|
||||||
|
this.textId = textId;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,4 +16,8 @@ public abstract class NavDrawerModule {
|
|||||||
abstract ViewModel bindNavDrawerViewModel(
|
abstract ViewModel bindNavDrawerViewModel(
|
||||||
NavDrawerViewModel navDrawerViewModel);
|
NavDrawerViewModel navDrawerViewModel);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ViewModelKey(PluginViewModel.class)
|
||||||
|
abstract ViewModel bindPluginViewModel(PluginViewModel pluginViewModel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,54 +4,36 @@ import android.app.Application;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
import org.briarproject.bramble.api.plugin.Plugin;
|
|
||||||
import org.briarproject.bramble.api.plugin.Plugin.State;
|
|
||||||
import org.briarproject.bramble.api.plugin.PluginManager;
|
|
||||||
import org.briarproject.bramble.api.plugin.TorConstants;
|
import org.briarproject.bramble.api.plugin.TorConstants;
|
||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
|
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
import org.briarproject.bramble.api.settings.SettingsManager;
|
import org.briarproject.bramble.api.settings.SettingsManager;
|
||||||
import org.briarproject.bramble.api.system.LocationUtils;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.DAYS;
|
import static java.util.concurrent.TimeUnit.DAYS;
|
||||||
import static java.util.logging.Level.INFO;
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.PREF_PLUGIN_ENABLE;
|
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
|
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE;
|
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
|
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
|
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ONLY_WHEN_CHARGING;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
|
import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
|
||||||
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
||||||
import static org.briarproject.briar.android.controller.BriarControllerImpl.DOZE_ASK_AGAIN;
|
import static org.briarproject.briar.android.controller.BriarControllerImpl.DOZE_ASK_AGAIN;
|
||||||
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.getCountryDisplayName;
|
|
||||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class NavDrawerViewModel extends AndroidViewModel
|
public class NavDrawerViewModel extends AndroidViewModel {
|
||||||
implements EventListener {
|
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(NavDrawerViewModel.class.getName());
|
getLogger(NavDrawerViewModel.class.getName());
|
||||||
@@ -63,53 +45,18 @@ public class NavDrawerViewModel extends AndroidViewModel
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private final Executor dbExecutor;
|
private final Executor dbExecutor;
|
||||||
private final SettingsManager settingsManager;
|
private final SettingsManager settingsManager;
|
||||||
private final PluginManager pluginManager;
|
|
||||||
private final LocationUtils locationUtils;
|
|
||||||
private final EventBus eventBus;
|
|
||||||
|
|
||||||
private final MutableLiveData<Boolean> showExpiryWarning =
|
private final MutableLiveData<Boolean> showExpiryWarning =
|
||||||
new MutableLiveData<>();
|
new MutableLiveData<>();
|
||||||
private final MutableLiveData<Boolean> shouldAskForDozeWhitelisting =
|
private final MutableLiveData<Boolean> shouldAskForDozeWhitelisting =
|
||||||
new MutableLiveData<>();
|
new MutableLiveData<>();
|
||||||
|
|
||||||
private final MutableLiveData<Plugin.State> torPluginState =
|
|
||||||
new MutableLiveData<>();
|
|
||||||
private final MutableLiveData<Plugin.State> wifiPluginState =
|
|
||||||
new MutableLiveData<>();
|
|
||||||
private final MutableLiveData<Plugin.State> btPluginState =
|
|
||||||
new MutableLiveData<>();
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
NavDrawerViewModel(Application app, @DatabaseExecutor Executor dbExecutor,
|
NavDrawerViewModel(Application app, @DatabaseExecutor Executor dbExecutor,
|
||||||
SettingsManager settingsManager, PluginManager pluginManager,
|
SettingsManager settingsManager) {
|
||||||
LocationUtils locationUtils, EventBus eventBus) {
|
|
||||||
super(app);
|
super(app);
|
||||||
this.dbExecutor = dbExecutor;
|
this.dbExecutor = dbExecutor;
|
||||||
this.settingsManager = settingsManager;
|
this.settingsManager = settingsManager;
|
||||||
this.pluginManager = pluginManager;
|
|
||||||
this.locationUtils = locationUtils;
|
|
||||||
this.eventBus = eventBus;
|
|
||||||
eventBus.addListener(this);
|
|
||||||
updatePluginStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCleared() {
|
|
||||||
eventBus.removeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void eventOccurred(Event e) {
|
|
||||||
if (e instanceof TransportStateEvent) {
|
|
||||||
TransportStateEvent t = (TransportStateEvent) e;
|
|
||||||
TransportId id = t.getTransportId();
|
|
||||||
State state = t.getState();
|
|
||||||
if (LOG.isLoggable(INFO)) {
|
|
||||||
LOG.info("TransportStateEvent: " + id + " is " + state);
|
|
||||||
}
|
|
||||||
MutableLiveData<Plugin.State> liveData = getPluginLiveData(id);
|
|
||||||
if (liveData != null) liveData.postValue(state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LiveData<Boolean> showExpiryWarning() {
|
LiveData<Boolean> showExpiryWarning() {
|
||||||
@@ -192,64 +139,4 @@ public class NavDrawerViewModel extends AndroidViewModel
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePluginStates() {
|
|
||||||
for (TransportId t : TRANSPORT_IDS) {
|
|
||||||
MutableLiveData<Plugin.State> liveData = getPluginLiveData(t);
|
|
||||||
if (liveData == null) throw new AssertionError();
|
|
||||||
liveData.setValue(getTransportState(t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private State getTransportState(TransportId id) {
|
|
||||||
Plugin plugin = pluginManager.getPlugin(id);
|
|
||||||
return plugin == null ? STARTING_STOPPING : plugin.getState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private MutableLiveData<State> getPluginLiveData(TransportId t) {
|
|
||||||
if (t.equals(TorConstants.ID)) {
|
|
||||||
return torPluginState;
|
|
||||||
} else if (t.equals(LanTcpConstants.ID)) {
|
|
||||||
return wifiPluginState;
|
|
||||||
} else if (t.equals(BluetoothConstants.ID)) {
|
|
||||||
return btPluginState;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LiveData<State> getPluginState(TransportId t) {
|
|
||||||
LiveData<Plugin.State> liveData = getPluginLiveData(t);
|
|
||||||
if (liveData == null) throw new AssertionError();
|
|
||||||
return liveData;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getReasonsDisabled(TransportId id) {
|
|
||||||
Plugin plugin = pluginManager.getPlugin(id);
|
|
||||||
return plugin == null ? 0 : plugin.getReasonsDisabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPluginEnabled(TransportId t, boolean enabled) {
|
|
||||||
pluginManager.setPluginEnabled(t, enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTorEnabled(boolean battery, boolean mobileData, boolean location) {
|
|
||||||
Settings s = new Settings();
|
|
||||||
s.putBoolean(PREF_PLUGIN_ENABLE, true);
|
|
||||||
if (battery) s.putBoolean(PREF_TOR_ONLY_WHEN_CHARGING, false);
|
|
||||||
if (mobileData) s.putBoolean(PREF_TOR_MOBILE, true);
|
|
||||||
if (location) s.putInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_WITH_BRIDGES);
|
|
||||||
dbExecutor.execute(() -> {
|
|
||||||
try {
|
|
||||||
settingsManager.mergeSettings(s, TorConstants.ID.getString());
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
String getCurrentCountryName() {
|
|
||||||
return getCountryDisplayName(locationUtils.getCurrentCountry());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,200 +0,0 @@
|
|||||||
package org.briarproject.briar.android.navdrawer;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.ScrollView;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
|
||||||
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
|
||||||
import org.briarproject.bramble.api.plugin.Plugin.State;
|
|
||||||
import org.briarproject.bramble.api.plugin.TorConstants;
|
|
||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
|
||||||
import org.briarproject.briar.R;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.widget.AppCompatImageButton;
|
|
||||||
import androidx.appcompat.widget.SwitchCompat;
|
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
|
||||||
import androidx.constraintlayout.widget.ConstraintSet;
|
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.transition.TransitionManager.beginDelayedTransition;
|
|
||||||
import static android.view.View.FOCUS_DOWN;
|
|
||||||
import static androidx.core.content.ContextCompat.getColor;
|
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.REASON_USER;
|
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
|
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING;
|
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
|
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY;
|
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED;
|
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA;
|
|
||||||
import static org.briarproject.briar.android.navdrawer.NavDrawerViewModel.TRANSPORT_IDS;
|
|
||||||
import static org.briarproject.briar.android.util.UiUtils.getDialogIcon;
|
|
||||||
|
|
||||||
class PluginViewController {
|
|
||||||
|
|
||||||
private final AppCompatActivity activity;
|
|
||||||
private final NavDrawerViewModel viewModel;
|
|
||||||
private final ConstraintLayout drawerContent;
|
|
||||||
private final ConstraintSet collapsedConstraints, expandedConstraints;
|
|
||||||
private final AppCompatImageButton chevronView;
|
|
||||||
private final ImageView torIcon, wifiIcon, btIcon;
|
|
||||||
private final SwitchCompat torSwitch, wifiSwitch, btSwitch;
|
|
||||||
|
|
||||||
private boolean expanded = false;
|
|
||||||
|
|
||||||
PluginViewController(View v, AppCompatActivity activity,
|
|
||||||
NavDrawerViewModel viewModel) {
|
|
||||||
this.activity = activity;
|
|
||||||
this.viewModel = viewModel;
|
|
||||||
drawerContent = v.findViewById(R.id.drawerContent);
|
|
||||||
|
|
||||||
collapsedConstraints = new ConstraintSet();
|
|
||||||
collapsedConstraints.clone(v.getContext(),
|
|
||||||
R.layout.navigation_menu_collapsed);
|
|
||||||
|
|
||||||
expandedConstraints = new ConstraintSet();
|
|
||||||
expandedConstraints.clone(v.getContext(),
|
|
||||||
R.layout.navigation_menu_expanded);
|
|
||||||
|
|
||||||
// Scroll the drawer to the bottom when the view is expanded/collapsed
|
|
||||||
ScrollView scrollView = v.findViewById(R.id.drawerScrollView);
|
|
||||||
drawerContent.addOnLayoutChangeListener((view, left, top, right,
|
|
||||||
bottom, oldLeft, oldTop, oldRight, oldBottom) ->
|
|
||||||
scrollView.fullScroll(FOCUS_DOWN));
|
|
||||||
|
|
||||||
// Clicking the chevron expands or collapses the view
|
|
||||||
chevronView = v.findViewById(R.id.chevronView);
|
|
||||||
chevronView.setOnClickListener(view -> expandOrCollapseView());
|
|
||||||
|
|
||||||
// The whole view is clickable when collapsed
|
|
||||||
v.findViewById(R.id.connectionsBackground).setOnClickListener(view ->
|
|
||||||
expandOrCollapseView());
|
|
||||||
|
|
||||||
torIcon = v.findViewById(R.id.torIcon);
|
|
||||||
wifiIcon = v.findViewById(R.id.wifiIcon);
|
|
||||||
btIcon = v.findViewById(R.id.btIcon);
|
|
||||||
|
|
||||||
torSwitch = v.findViewById(R.id.torSwitch);
|
|
||||||
wifiSwitch = v.findViewById(R.id.wifiSwitch);
|
|
||||||
btSwitch = v.findViewById(R.id.btSwitch);
|
|
||||||
|
|
||||||
for (TransportId t : TRANSPORT_IDS) {
|
|
||||||
// a OnCheckedChangeListener would get triggered on programmatic updates
|
|
||||||
SwitchCompat switchCompat = getSwitch(t);
|
|
||||||
switchCompat.setOnClickListener(buttonView -> {
|
|
||||||
if (switchCompat.isChecked()) tryToEnablePlugin(t);
|
|
||||||
else viewModel.setPluginEnabled(t, false);
|
|
||||||
// Revert the switch to its previous state until the plugin
|
|
||||||
// changes its state
|
|
||||||
switchCompat.toggle();
|
|
||||||
});
|
|
||||||
viewModel.getPluginState(t).observe(activity, state ->
|
|
||||||
stateUpdate(t, state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expandOrCollapseView() {
|
|
||||||
if (SDK_INT >= 19) beginDelayedTransition(drawerContent);
|
|
||||||
if (expanded) {
|
|
||||||
collapsedConstraints.applyTo(drawerContent);
|
|
||||||
chevronView.setImageResource(R.drawable.chevron_up_white);
|
|
||||||
} else {
|
|
||||||
expandedConstraints.applyTo(drawerContent);
|
|
||||||
chevronView.setImageResource(R.drawable.chevron_down_white);
|
|
||||||
}
|
|
||||||
expanded = !expanded;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void tryToEnablePlugin(TransportId id) {
|
|
||||||
if (id.equals(TorConstants.ID)) {
|
|
||||||
int reasons = viewModel.getReasonsDisabled(id);
|
|
||||||
if (reasons == 0 || reasons == REASON_USER) {
|
|
||||||
viewModel.setPluginEnabled(id, true);
|
|
||||||
} else {
|
|
||||||
showTorSettingsDialog(reasons);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
viewModel.setPluginEnabled(id, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stateUpdate(TransportId id, State state) {
|
|
||||||
updateIcon(getIcon(id), state);
|
|
||||||
updateSwitch(getSwitch(id), state);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SwitchCompat getSwitch(TransportId id) {
|
|
||||||
if (id == TorConstants.ID) return torSwitch;
|
|
||||||
if (id == BluetoothConstants.ID) return btSwitch;
|
|
||||||
if (id == LanTcpConstants.ID) return wifiSwitch;
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSwitch(SwitchCompat switchCompat, State state) {
|
|
||||||
boolean checked = state != STARTING_STOPPING && state != DISABLED;
|
|
||||||
switchCompat.setChecked(checked);
|
|
||||||
switchCompat.setEnabled(state != STARTING_STOPPING);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ImageView getIcon(TransportId id) {
|
|
||||||
if (id == TorConstants.ID) return torIcon;
|
|
||||||
if (id == BluetoothConstants.ID) return btIcon;
|
|
||||||
if (id == LanTcpConstants.ID) return wifiIcon;
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateIcon(ImageView icon, State state) {
|
|
||||||
int colorRes;
|
|
||||||
if (state == ACTIVE) {
|
|
||||||
colorRes = R.color.briar_green_light;
|
|
||||||
} else if (state == ENABLING) {
|
|
||||||
colorRes = R.color.briar_yellow;
|
|
||||||
} else {
|
|
||||||
colorRes = android.R.color.tertiary_text_light;
|
|
||||||
}
|
|
||||||
int color = getColor(icon.getContext(), colorRes);
|
|
||||||
icon.setColorFilter(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showTorSettingsDialog(int reasonsDisabled) {
|
|
||||||
boolean battery = (reasonsDisabled & REASON_BATTERY) != 0;
|
|
||||||
boolean mobileData = (reasonsDisabled & REASON_MOBILE_DATA) != 0;
|
|
||||||
boolean location = (reasonsDisabled & REASON_COUNTRY_BLOCKED) != 0;
|
|
||||||
|
|
||||||
StringBuilder s = new StringBuilder();
|
|
||||||
if (location) {
|
|
||||||
s.append("\t\u2022 ");
|
|
||||||
s.append(activity.getString(R.string.tor_override_network_setting,
|
|
||||||
viewModel.getCurrentCountryName()));
|
|
||||||
s.append('\n');
|
|
||||||
}
|
|
||||||
if (mobileData) {
|
|
||||||
s.append("\t\u2022 ");
|
|
||||||
s.append(activity.getString(
|
|
||||||
R.string.tor_override_mobile_data_setting));
|
|
||||||
s.append('\n');
|
|
||||||
}
|
|
||||||
if (battery) {
|
|
||||||
s.append("\t\u2022 ");
|
|
||||||
s.append(activity.getString(R.string.tor_only_when_charging_title));
|
|
||||||
s.append('\n');
|
|
||||||
}
|
|
||||||
String message = activity.getString(
|
|
||||||
R.string.tor_override_settings_body, s.toString());
|
|
||||||
|
|
||||||
AlertDialog.Builder b =
|
|
||||||
new AlertDialog.Builder(activity, R.style.BriarDialogTheme);
|
|
||||||
b.setTitle(R.string.tor_override_settings_title);
|
|
||||||
b.setIcon(getDialogIcon(activity, R.drawable.ic_settings_black_24dp));
|
|
||||||
b.setMessage(message);
|
|
||||||
b.setPositiveButton(R.string.tor_override_settings_confirm,
|
|
||||||
(dialog, which) ->
|
|
||||||
viewModel.setTorEnabled(battery, mobileData, location));
|
|
||||||
b.setNegativeButton(R.string.cancel, (dialog, which) ->
|
|
||||||
dialog.dismiss());
|
|
||||||
b.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
package org.briarproject.briar.android.navdrawer;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.event.Event;
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.Plugin;
|
||||||
|
import org.briarproject.bramble.api.plugin.Plugin.State;
|
||||||
|
import org.briarproject.bramble.api.plugin.PluginManager;
|
||||||
|
import org.briarproject.bramble.api.plugin.TorConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
|
import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
|
||||||
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
import org.briarproject.bramble.api.settings.SettingsManager;
|
||||||
|
import org.briarproject.bramble.api.system.LocationUtils;
|
||||||
|
import org.briarproject.briar.R;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import static java.util.logging.Level.INFO;
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
import static org.briarproject.bramble.api.plugin.Plugin.PREF_PLUGIN_ENABLE;
|
||||||
|
import static org.briarproject.bramble.api.plugin.Plugin.REASON_USER;
|
||||||
|
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ONLY_WHEN_CHARGING;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.briar.android.navdrawer.NavDrawerViewModel.TRANSPORT_IDS;
|
||||||
|
import static org.briarproject.briar.android.util.UiUtils.getCountryDisplayName;
|
||||||
|
import static org.briarproject.briar.android.util.UiUtils.getDialogIcon;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
public class PluginViewModel extends AndroidViewModel implements EventListener {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
getLogger(PluginViewModel.class.getName());
|
||||||
|
|
||||||
|
private final Application app;
|
||||||
|
@DatabaseExecutor
|
||||||
|
private final Executor dbExecutor;
|
||||||
|
private final SettingsManager settingsManager;
|
||||||
|
private final PluginManager pluginManager;
|
||||||
|
private final LocationUtils locationUtils;
|
||||||
|
private final EventBus eventBus;
|
||||||
|
|
||||||
|
private final MutableLiveData<State> torPluginState =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<State> wifiPluginState =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<State> btPluginState =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PluginViewModel(Application app, @DatabaseExecutor Executor dbExecutor,
|
||||||
|
SettingsManager settingsManager, PluginManager pluginManager,
|
||||||
|
LocationUtils locationUtils, EventBus eventBus) {
|
||||||
|
super(app);
|
||||||
|
this.app = app;
|
||||||
|
this.dbExecutor = dbExecutor;
|
||||||
|
this.settingsManager = settingsManager;
|
||||||
|
this.pluginManager = pluginManager;
|
||||||
|
this.locationUtils = locationUtils;
|
||||||
|
this.eventBus = eventBus;
|
||||||
|
eventBus.addListener(this);
|
||||||
|
initialisePluginStates();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCleared() {
|
||||||
|
eventBus.removeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventOccurred(Event e) {
|
||||||
|
if (e instanceof TransportStateEvent) {
|
||||||
|
TransportStateEvent t = (TransportStateEvent) e;
|
||||||
|
TransportId id = t.getTransportId();
|
||||||
|
State state = t.getState();
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("TransportStateEvent: " + id + " is " + state);
|
||||||
|
}
|
||||||
|
MutableLiveData<State> liveData = getPluginLiveData(id);
|
||||||
|
liveData.postValue(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSwitchClicked(TransportId t, boolean isChecked) {
|
||||||
|
if (isChecked) tryToEnablePlugin(t);
|
||||||
|
else setPluginEnabled(t, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<State> getPluginState(TransportId t) {
|
||||||
|
return getPluginLiveData(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryToEnablePlugin(TransportId id) {
|
||||||
|
if (id.equals(TorConstants.ID)) {
|
||||||
|
int reasons = getReasonsDisabled(id);
|
||||||
|
if (reasons == 0 || reasons == REASON_USER) {
|
||||||
|
setPluginEnabled(id, true);
|
||||||
|
} else {
|
||||||
|
showTorSettingsDialog(reasons);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setPluginEnabled(id, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialisePluginStates() {
|
||||||
|
for (TransportId t : TRANSPORT_IDS) {
|
||||||
|
MutableLiveData<State> liveData = getPluginLiveData(t);
|
||||||
|
liveData.setValue(getTransportState(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private State getTransportState(TransportId id) {
|
||||||
|
Plugin plugin = pluginManager.getPlugin(id);
|
||||||
|
return plugin == null ? STARTING_STOPPING : plugin.getState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MutableLiveData<State> getPluginLiveData(TransportId t) {
|
||||||
|
if (t.equals(TorConstants.ID)) {
|
||||||
|
return torPluginState;
|
||||||
|
} else if (t.equals(LanTcpConstants.ID)) {
|
||||||
|
return wifiPluginState;
|
||||||
|
} else if (t.equals(BluetoothConstants.ID)) {
|
||||||
|
return btPluginState;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getReasonsDisabled(TransportId id) {
|
||||||
|
Plugin plugin = pluginManager.getPlugin(id);
|
||||||
|
return plugin == null ? 0 : plugin.getReasonsDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPluginEnabled(TransportId t, boolean enabled) {
|
||||||
|
pluginManager.setPluginEnabled(t, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTorEnabled(boolean battery, boolean mobileData,
|
||||||
|
boolean location) {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putBoolean(PREF_PLUGIN_ENABLE, true);
|
||||||
|
if (battery) s.putBoolean(PREF_TOR_ONLY_WHEN_CHARGING, false);
|
||||||
|
if (mobileData) s.putBoolean(PREF_TOR_MOBILE, true);
|
||||||
|
if (location) s.putInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_WITH_BRIDGES);
|
||||||
|
dbExecutor.execute(() -> {
|
||||||
|
try {
|
||||||
|
settingsManager.mergeSettings(s, TorConstants.ID.getString());
|
||||||
|
} catch (DbException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showTorSettingsDialog(int reasonsDisabled) {
|
||||||
|
boolean battery = (reasonsDisabled & REASON_BATTERY) != 0;
|
||||||
|
boolean mobileData = (reasonsDisabled & REASON_MOBILE_DATA) != 0;
|
||||||
|
boolean location = (reasonsDisabled & REASON_COUNTRY_BLOCKED) != 0;
|
||||||
|
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
if (location) {
|
||||||
|
s.append("\t\u2022 ");
|
||||||
|
s.append(app.getString(R.string.tor_override_network_setting,
|
||||||
|
getCountryDisplayName(locationUtils.getCurrentCountry())));
|
||||||
|
s.append('\n');
|
||||||
|
}
|
||||||
|
if (mobileData) {
|
||||||
|
s.append("\t\u2022 ");
|
||||||
|
s.append(app.getString(R.string.tor_override_mobile_data_setting));
|
||||||
|
s.append('\n');
|
||||||
|
}
|
||||||
|
if (battery) {
|
||||||
|
s.append("\t\u2022 ");
|
||||||
|
s.append(app.getString(R.string.tor_only_when_charging_title));
|
||||||
|
s.append('\n');
|
||||||
|
}
|
||||||
|
String message = app.getString(
|
||||||
|
R.string.tor_override_settings_body, s.toString());
|
||||||
|
|
||||||
|
AlertDialog.Builder b =
|
||||||
|
new AlertDialog.Builder(app, R.style.BriarDialogTheme);
|
||||||
|
b.setTitle(R.string.tor_override_settings_title);
|
||||||
|
b.setIcon(getDialogIcon(app, R.drawable.ic_settings_black_24dp));
|
||||||
|
b.setMessage(message);
|
||||||
|
b.setPositiveButton(R.string.tor_override_settings_confirm,
|
||||||
|
(dialog, which) ->
|
||||||
|
setTorEnabled(battery, mobileData, location));
|
||||||
|
b.setNegativeButton(R.string.cancel, (dialog, which) ->
|
||||||
|
dialog.dismiss());
|
||||||
|
b.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,8 @@ import org.briarproject.bramble.api.event.EventBus;
|
|||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
import org.briarproject.bramble.api.plugin.TorConstants;
|
import org.briarproject.bramble.api.plugin.TorConstants;
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
import org.briarproject.bramble.api.settings.SettingsManager;
|
import org.briarproject.bramble.api.settings.SettingsManager;
|
||||||
@@ -113,7 +115,15 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
"pref_key_lock_timeout";
|
"pref_key_lock_timeout";
|
||||||
public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in";
|
public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in";
|
||||||
|
|
||||||
|
private static final String BT_NAMESPACE =
|
||||||
|
BluetoothConstants.ID.getString();
|
||||||
|
private static final String BT_ENABLE = "pref_key_bluetooth";
|
||||||
|
|
||||||
|
private static final String WIFI_NAMESPACE = LanTcpConstants.ID.getString();
|
||||||
|
private static final String WIFI_ENABLE = "pref_key_wifi";
|
||||||
|
|
||||||
private static final String TOR_NAMESPACE = TorConstants.ID.getString();
|
private static final String TOR_NAMESPACE = TorConstants.ID.getString();
|
||||||
|
private static final String TOR_ENABLE = "pref_key_tor_enable";
|
||||||
private static final String TOR_NETWORK = "pref_key_tor_network";
|
private static final String TOR_NETWORK = "pref_key_tor_network";
|
||||||
private static final String TOR_MOBILE = "pref_key_tor_mobile_data";
|
private static final String TOR_MOBILE = "pref_key_tor_mobile_data";
|
||||||
private static final String TOR_ONLY_WHEN_CHARGING =
|
private static final String TOR_ONLY_WHEN_CHARGING =
|
||||||
@@ -124,6 +134,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
|
|
||||||
private SettingsActivity listener;
|
private SettingsActivity listener;
|
||||||
private ListPreference language;
|
private ListPreference language;
|
||||||
|
private SwitchPreference enableBluetooth;
|
||||||
|
private SwitchPreference enableWifi;
|
||||||
|
private SwitchPreference enableTor;
|
||||||
private ListPreference torNetwork;
|
private ListPreference torNetwork;
|
||||||
private SwitchPreference torMobile;
|
private SwitchPreference torMobile;
|
||||||
private SwitchPreference torOnlyWhenCharging;
|
private SwitchPreference torOnlyWhenCharging;
|
||||||
@@ -138,7 +151,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
private Preference notifySound;
|
private Preference notifySound;
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
// Fields that are accessed from background threads must be volatile
|
||||||
private volatile Settings settings, torSettings;
|
private volatile Settings settings, btSettings, wifiSettings, torSettings;
|
||||||
private volatile boolean settingsLoaded = false;
|
private volatile boolean settingsLoaded = false;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -167,6 +180,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
language = findPreference(LANGUAGE);
|
language = findPreference(LANGUAGE);
|
||||||
setLanguageEntries();
|
setLanguageEntries();
|
||||||
ListPreference theme = findPreference("pref_key_theme");
|
ListPreference theme = findPreference("pref_key_theme");
|
||||||
|
enableBluetooth = findPreference(BT_ENABLE);
|
||||||
|
enableWifi = findPreference(WIFI_ENABLE);
|
||||||
|
enableTor = findPreference(TOR_ENABLE);
|
||||||
torNetwork = findPreference(TOR_NETWORK);
|
torNetwork = findPreference(TOR_NETWORK);
|
||||||
torMobile = findPreference(TOR_MOBILE);
|
torMobile = findPreference(TOR_MOBILE);
|
||||||
torOnlyWhenCharging = findPreference(TOR_ONLY_WHEN_CHARGING);
|
torOnlyWhenCharging = findPreference(TOR_ONLY_WHEN_CHARGING);
|
||||||
@@ -198,6 +214,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
enableBluetooth.setOnPreferenceChangeListener(this);
|
||||||
|
enableWifi.setOnPreferenceChangeListener(this);
|
||||||
|
enableTor.setOnPreferenceChangeListener(this);
|
||||||
torNetwork.setOnPreferenceChangeListener(this);
|
torNetwork.setOnPreferenceChangeListener(this);
|
||||||
torMobile.setOnPreferenceChangeListener(this);
|
torMobile.setOnPreferenceChangeListener(this);
|
||||||
torOnlyWhenCharging.setOnPreferenceChangeListener(this);
|
torOnlyWhenCharging.setOnPreferenceChangeListener(this);
|
||||||
@@ -339,8 +358,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||||
torSettings = migrateTorSettings(
|
btSettings = settingsManager.getSettings(BT_NAMESPACE);
|
||||||
settingsManager.getSettings(TOR_NAMESPACE));
|
wifiSettings = settingsManager.getSettings(WIFI_NAMESPACE);
|
||||||
|
torSettings = settingsManager.getSettings(TOR_NAMESPACE);
|
||||||
settingsLoaded = true;
|
settingsLoaded = true;
|
||||||
logDuration(LOG, "Loading settings", start);
|
logDuration(LOG, "Loading settings", start);
|
||||||
displaySettings();
|
displaySettings();
|
||||||
@@ -368,6 +388,18 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
// due to events, we might try to display before a load completed
|
// due to events, we might try to display before a load completed
|
||||||
if (!settingsLoaded) return;
|
if (!settingsLoaded) return;
|
||||||
|
|
||||||
|
boolean btEnabledSetting =
|
||||||
|
btSettings.getBoolean(PREF_PLUGIN_ENABLE, false);
|
||||||
|
enableBluetooth.setChecked(btEnabledSetting);
|
||||||
|
|
||||||
|
boolean wifiEnabledSetting =
|
||||||
|
wifiSettings.getBoolean(PREF_PLUGIN_ENABLE, false);
|
||||||
|
enableWifi.setChecked(wifiEnabledSetting);
|
||||||
|
|
||||||
|
boolean torEnabledSetting =
|
||||||
|
torSettings.getBoolean(PREF_PLUGIN_ENABLE, true);
|
||||||
|
enableTor.setChecked(torEnabledSetting);
|
||||||
|
|
||||||
int torNetworkSetting = torSettings.getInt(PREF_TOR_NETWORK,
|
int torNetworkSetting = torSettings.getInt(PREF_TOR_NETWORK,
|
||||||
PREF_TOR_NETWORK_AUTOMATIC);
|
PREF_TOR_NETWORK_AUTOMATIC);
|
||||||
torNetwork.setValue(Integer.toString(torNetworkSetting));
|
torNetwork.setValue(Integer.toString(torNetworkSetting));
|
||||||
@@ -439,6 +471,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
// preferences partly needed here, because they have their own logic
|
// preferences partly needed here, because they have their own logic
|
||||||
// - pref_key_lock (screenLock -> displayScreenLockSetting())
|
// - pref_key_lock (screenLock -> displayScreenLockSetting())
|
||||||
// - pref_key_lock_timeout (screenLockTimeout)
|
// - pref_key_lock_timeout (screenLockTimeout)
|
||||||
|
enableBluetooth.setEnabled(enabled);
|
||||||
|
enableWifi.setEnabled(enabled);
|
||||||
|
enableTor.setEnabled(enabled);
|
||||||
torNetwork.setEnabled(enabled);
|
torNetwork.setEnabled(enabled);
|
||||||
torMobile.setEnabled(enabled);
|
torMobile.setEnabled(enabled);
|
||||||
torOnlyWhenCharging.setEnabled(enabled);
|
torOnlyWhenCharging.setEnabled(enabled);
|
||||||
@@ -540,6 +575,15 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
if (!language.getValue().equals(newValue))
|
if (!language.getValue().equals(newValue))
|
||||||
languageChanged((String) newValue);
|
languageChanged((String) newValue);
|
||||||
return false;
|
return false;
|
||||||
|
} else if (preference == enableBluetooth) {
|
||||||
|
boolean btSetting = (Boolean) newValue;
|
||||||
|
storeBluetoothSetting(btSetting);
|
||||||
|
} else if (preference == enableWifi) {
|
||||||
|
boolean wifiSetting = (Boolean) newValue;
|
||||||
|
storeWifiSetting(wifiSetting);
|
||||||
|
} else if (preference == enableTor) {
|
||||||
|
boolean torEnabledSetting = (Boolean) newValue;
|
||||||
|
storeTorEnabledSetting(torEnabledSetting);
|
||||||
} else if (preference == torNetwork) {
|
} else if (preference == torNetwork) {
|
||||||
int torNetworkSetting = Integer.valueOf((String) newValue);
|
int torNetworkSetting = Integer.valueOf((String) newValue);
|
||||||
storeTorNetworkSetting(torNetworkSetting);
|
storeTorNetworkSetting(torNetworkSetting);
|
||||||
@@ -603,6 +647,12 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
builder.show();
|
builder.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void storeTorEnabledSetting(boolean torEnabledSetting) {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putBoolean(PREF_PLUGIN_ENABLE, torEnabledSetting);
|
||||||
|
mergeSettings(s, TOR_NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
private void storeTorNetworkSetting(int torNetworkSetting) {
|
private void storeTorNetworkSetting(int torNetworkSetting) {
|
||||||
Settings s = new Settings();
|
Settings s = new Settings();
|
||||||
s.putInt(PREF_TOR_NETWORK, torNetworkSetting);
|
s.putInt(PREF_TOR_NETWORK, torNetworkSetting);
|
||||||
@@ -621,6 +671,18 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
mergeSettings(s, TOR_NAMESPACE);
|
mergeSettings(s, TOR_NAMESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void storeBluetoothSetting(boolean btSetting) {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putBoolean(PREF_PLUGIN_ENABLE, btSetting);
|
||||||
|
mergeSettings(s, BT_NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void storeWifiSetting(boolean wifiSetting) {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putBoolean(PREF_PLUGIN_ENABLE, wifiSetting);
|
||||||
|
mergeSettings(s, WIFI_NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
private void storeSettings(Settings s) {
|
private void storeSettings(Settings s) {
|
||||||
mergeSettings(s, SETTINGS_NAMESPACE);
|
mergeSettings(s, SETTINGS_NAMESPACE);
|
||||||
}
|
}
|
||||||
@@ -679,6 +741,14 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
LOG.info("Settings updated");
|
LOG.info("Settings updated");
|
||||||
settings = s.getSettings();
|
settings = s.getSettings();
|
||||||
displaySettings();
|
displaySettings();
|
||||||
|
} else if (namespace.equals(BT_NAMESPACE)) {
|
||||||
|
LOG.info("Bluetooth settings updated");
|
||||||
|
btSettings = s.getSettings();
|
||||||
|
displaySettings();
|
||||||
|
} else if (namespace.equals(WIFI_NAMESPACE)) {
|
||||||
|
LOG.info("Wifi settings updated");
|
||||||
|
wifiSettings = s.getSettings();
|
||||||
|
displaySettings();
|
||||||
} else if (namespace.equals(TOR_NAMESPACE)) {
|
} else if (namespace.equals(TOR_NAMESPACE)) {
|
||||||
LOG.info("Tor settings updated");
|
LOG.info("Tor settings updated");
|
||||||
torSettings = migrateTorSettings(s.getSettings());
|
torSettings = migrateTorSettings(s.getSettings());
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<group>
|
|
||||||
<path
|
|
||||||
android:fillColor="#000000"
|
|
||||||
android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4v2z" />
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
|
|
||||||
@@ -1,12 +1,59 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/drawerScrollView"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/window_background"
|
android:background="@color/window_background"
|
||||||
android:fillViewport="true"
|
android:fillViewport="true"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<include layout="@layout/navigation_menu_collapsed" />
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.navigation.NavigationView
|
||||||
|
android:id="@+id/navigation"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/window_background"
|
||||||
|
app:elevation="0dp"
|
||||||
|
app:headerLayout="@layout/navigation_header"
|
||||||
|
app:itemBackground="@drawable/navigation_item_background"
|
||||||
|
app:itemIconTint="?attr/colorControlNormal"
|
||||||
|
app:itemTextColor="?android:textColorPrimary"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:menu="@menu/navigation_drawer" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider1"
|
||||||
|
style="@style/Divider.Horizontal"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/navigation"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/navigation" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/spacer"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/transports"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/divider1"
|
||||||
|
app:layout_constraintVertical_weight="1" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/transports"
|
||||||
|
layout="@layout/transports_list"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/navigation"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/spacer"
|
||||||
|
tools:layout_height="75dp" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/drawerContent"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@color/window_background">
|
|
||||||
|
|
||||||
<com.google.android.material.navigation.NavigationView
|
|
||||||
android:id="@+id/navigation"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@color/window_background"
|
|
||||||
app:elevation="0dp"
|
|
||||||
app:headerLayout="@layout/navigation_header"
|
|
||||||
app:itemBackground="@drawable/navigation_item_background"
|
|
||||||
app:itemIconTint="?attr/colorControlNormal"
|
|
||||||
app:itemTextColor="?android:textColorPrimary"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_bias="0.0"
|
|
||||||
app:menu="@menu/navigation_drawer" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageButton
|
|
||||||
android:id="@+id/chevronView"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="@color/divider"
|
|
||||||
android:foreground="?attr/selectableItemBackground"
|
|
||||||
android:src="@drawable/chevron_up_white"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/connectionsLabel"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/navigation"
|
|
||||||
app:layout_constraintVertical_bias="1.0"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
app:tint="?attr/colorControlNormal"
|
|
||||||
tools:ignore="ContentDescription,UnusedAttribute" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/connectionsBackground"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chevronView" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/connectionsLabel"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:text="@string/transport_connection"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:visibility="visible"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/torIcon"
|
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chevronView" />
|
|
||||||
|
|
||||||
<!-- Hidden -->
|
|
||||||
<View
|
|
||||||
android:id="@+id/longRangeBackground"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:background="@color/item_background_highlight"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
<!-- Hidden -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/longRangeLabel"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:text="@string/transport_internet"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/torIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:src="@drawable/transport_tor"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/wifiIcon"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chevronView"
|
|
||||||
tools:ignore="ContentDescription"
|
|
||||||
tools:tint="@color/briar_green" />
|
|
||||||
|
|
||||||
<!-- Hidden -->
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
|
||||||
android:id="@+id/torSwitch"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:text="@string/transport_tor"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
<!-- Hidden -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/nearbyLabel"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:text="@string/transport_nearby"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/wifiIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:src="@drawable/transport_lan"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/btIcon"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chevronView"
|
|
||||||
tools:checked="true"
|
|
||||||
tools:ignore="ContentDescription"
|
|
||||||
tools:tint="@color/briar_green" />
|
|
||||||
|
|
||||||
<!-- Hidden -->
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
|
||||||
android:id="@+id/wifiSwitch"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:text="@string/transport_lan"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/btIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:src="@drawable/transport_bt"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chevronView"
|
|
||||||
tools:checked="true"
|
|
||||||
tools:ignore="ContentDescription"
|
|
||||||
tools:tint="@color/briar_green" />
|
|
||||||
|
|
||||||
<!-- Hidden -->
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
|
||||||
android:id="@+id/btSwitch"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:text="@string/transport_bt"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/drawerContent"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@color/window_background">
|
|
||||||
|
|
||||||
<com.google.android.material.navigation.NavigationView
|
|
||||||
android:id="@+id/navigation"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@color/window_background"
|
|
||||||
app:elevation="0dp"
|
|
||||||
app:headerLayout="@layout/navigation_header"
|
|
||||||
app:itemBackground="@drawable/navigation_item_background"
|
|
||||||
app:itemIconTint="?attr/colorControlNormal"
|
|
||||||
app:itemTextColor="?android:textColorPrimary"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_bias="0.0"
|
|
||||||
app:menu="@menu/navigation_drawer" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageButton
|
|
||||||
android:id="@+id/chevronView"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="@color/divider"
|
|
||||||
android:foreground="?attr/selectableItemBackground"
|
|
||||||
android:src="@drawable/chevron_down_white"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/longRangeLabel"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/navigation"
|
|
||||||
app:layout_constraintVertical_bias="1.0"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
app:tint="?attr/colorControlNormal"
|
|
||||||
tools:ignore="ContentDescription,UnusedAttribute" />
|
|
||||||
|
|
||||||
<!-- Hidden -->
|
|
||||||
<View
|
|
||||||
android:id="@+id/connectionsBackground"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
<!-- Hidden -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/connectionsLabel"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:text="@string/transport_connection"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/longRangeBackground"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="@color/item_background_highlight"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/nearbyLabel"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chevronView" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/longRangeLabel"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:text="@string/transport_internet"
|
|
||||||
android:textSize="12sp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/torSwitch"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/torIcon"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chevronView" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/torIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:src="@drawable/transport_tor"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/torSwitch"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/torSwitch"
|
|
||||||
tools:ignore="ContentDescription"
|
|
||||||
tools:tint="@color/briar_green" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
|
||||||
android:id="@+id/torSwitch"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:text="@string/transport_tor"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/nearbyLabel"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/torIcon"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/longRangeLabel"
|
|
||||||
tools:checked="true" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/nearbyLabel"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:text="@string/transport_nearby"
|
|
||||||
android:textSize="12sp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/wifiSwitch"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/torIcon"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/torSwitch" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/wifiIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:src="@drawable/transport_lan"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/wifiSwitch"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/wifiSwitch"
|
|
||||||
tools:checked="true"
|
|
||||||
tools:ignore="ContentDescription"
|
|
||||||
tools:tint="@color/briar_green" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
|
||||||
android:id="@+id/wifiSwitch"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:text="@string/transport_lan"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/btSwitch"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/wifiIcon"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/nearbyLabel"
|
|
||||||
tools:checked="true" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/btIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:src="@drawable/transport_bt"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/btSwitch"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/btSwitch"
|
|
||||||
tools:checked="true"
|
|
||||||
tools:ignore="ContentDescription"
|
|
||||||
tools:tint="@color/briar_green" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
|
||||||
android:id="@+id/btSwitch"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:text="@string/transport_bt"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/btIcon"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/wifiSwitch"
|
|
||||||
tools:checked="true" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
19
briar-android/src/main/res/layout/transports_list.xml
Normal file
19
briar-android/src/main/res/layout/transports_list.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:showIn="@layout/navigation_menu">
|
||||||
|
|
||||||
|
<View style="@style/Divider.Horizontal" />
|
||||||
|
|
||||||
|
<GridView
|
||||||
|
android:id="@+id/transportsView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:listSelector="@android:color/transparent"
|
||||||
|
android:numColumns="3"
|
||||||
|
tools:listitem="@layout/list_item_transport" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -70,10 +70,7 @@
|
|||||||
<string name="sign_out_button">Sign Out</string>
|
<string name="sign_out_button">Sign Out</string>
|
||||||
|
|
||||||
<!-- Transports -->
|
<!-- Transports -->
|
||||||
<string name="transport_connection">Connections</string>
|
<string name="transport_tor">Internet</string>
|
||||||
<string name="transport_internet">Internet</string>
|
|
||||||
<string name="transport_tor">Tor</string>
|
|
||||||
<string name="transport_nearby">Nearby</string>
|
|
||||||
<string name="transport_bt">Bluetooth</string>
|
<string name="transport_bt">Bluetooth</string>
|
||||||
<string name="transport_lan">Wi-Fi</string>
|
<string name="transport_lan">Wi-Fi</string>
|
||||||
|
|
||||||
@@ -440,15 +437,19 @@
|
|||||||
|
|
||||||
<!-- Settings Connections -->
|
<!-- Settings Connections -->
|
||||||
<string name="network_settings_title">Connections</string>
|
<string name="network_settings_title">Connections</string>
|
||||||
<string name="tor_network_setting">Connection method for Internet (Tor)</string>
|
<string name="bluetooth_setting">Connect to contacts via Bluetooth</string>
|
||||||
|
<string name="wifi_setting">Connect to contacts on the same Wi-Fi network</string>
|
||||||
|
<string name="tor_enable_title">Connect to contacts via the Internet</string>
|
||||||
|
<string name="tor_enable_summary">All connections go through the Tor network for privacy</string>
|
||||||
|
<string name="tor_network_setting">Connection method for Tor network</string>
|
||||||
<string name="tor_network_setting_automatic">Automatic based on location</string>
|
<string name="tor_network_setting_automatic">Automatic based on location</string>
|
||||||
<string name="tor_network_setting_without_bridges">Use Tor without bridges</string>
|
<string name="tor_network_setting_without_bridges">Use Tor network without bridges</string>
|
||||||
<string name="tor_network_setting_with_bridges">Use Tor with bridges</string>
|
<string name="tor_network_setting_with_bridges">Use Tor network with bridges</string>
|
||||||
<string name="tor_network_setting_never">Don\'t connect</string>
|
<string name="tor_network_setting_never">Don\'t connect to the Internet</string>
|
||||||
<!-- How and when Tor will connect after Automatic: E.g. Don't connect (in China) or Use Tor with bridges (in Belarus) -->
|
<!-- How and when Briar will connect to Tor: E.g. "Don't connect to the Internet (in China)" or "Use Tor network with bridges (in Belarus)" -->
|
||||||
<string name="tor_network_setting_summary">Automatic: %1$s (in %2$s)</string>
|
<string name="tor_network_setting_summary">Automatic: %1$s (in %2$s)</string>
|
||||||
<string name="tor_mobile_data_title">Use mobile data</string>
|
<string name="tor_mobile_data_title">Use mobile data</string>
|
||||||
<string name="tor_only_when_charging_title">Connect via Internet (Tor) only when charging</string>
|
<string name="tor_only_when_charging_title">Connect to the Internet only when charging</string>
|
||||||
<string name="tor_only_when_charging_summary">Disables Internet connection when device is running on battery</string>
|
<string name="tor_only_when_charging_summary">Disables Internet connection when device is running on battery</string>
|
||||||
|
|
||||||
<!-- Settings Security and Panic -->
|
<!-- Settings Security and Panic -->
|
||||||
@@ -571,9 +572,9 @@
|
|||||||
|
|
||||||
<!-- Overriding Tor settings -->
|
<!-- Overriding Tor settings -->
|
||||||
<string name="tor_override_settings_title">Change Settings</string>
|
<string name="tor_override_settings_title">Change Settings</string>
|
||||||
<string name="tor_override_settings_body">Turning on Tor will change the following settings:\n\n%1$s</string>
|
<string name="tor_override_settings_body">Turning on connections via the Internet will change the following settings:\n\n%1$s</string>
|
||||||
<string name="tor_override_mobile_data_setting">Don\'t use mobile data</string>
|
<string name="tor_override_mobile_data_setting">Don\'t use mobile data</string>
|
||||||
<string name="tor_override_network_setting">Don\'t connect to Internet (Tor) in %1$s</string>
|
<string name="tor_override_network_setting">Don\'t connect to the Internet in %1$s</string>
|
||||||
<string name="tor_override_settings_confirm">Change</string>
|
<string name="tor_override_settings_confirm">Change</string>
|
||||||
|
|
||||||
<!-- Screenshots -->
|
<!-- Screenshots -->
|
||||||
|
|||||||
@@ -29,8 +29,34 @@
|
|||||||
android:layout="@layout/preferences_category"
|
android:layout="@layout/preferences_category"
|
||||||
android:title="@string/network_settings_title">
|
android:title="@string/network_settings_title">
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="pref_key_bluetooth"
|
||||||
|
android:persistent="false"
|
||||||
|
android:title="@string/bluetooth_setting"
|
||||||
|
android:widgetLayout="@layout/preference_switch_compat"
|
||||||
|
app:iconSpaceReserved="false"/>
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="pref_key_wifi"
|
||||||
|
android:persistent="false"
|
||||||
|
android:title="@string/wifi_setting"
|
||||||
|
android:widgetLayout="@layout/preference_switch_compat"
|
||||||
|
app:iconSpaceReserved="false"/>
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="pref_key_tor_enable"
|
||||||
|
android:persistent="false"
|
||||||
|
android:title="@string/tor_enable_title"
|
||||||
|
android:summary="@string/tor_enable_summary"
|
||||||
|
android:widgetLayout="@layout/preference_switch_compat"
|
||||||
|
app:iconSpaceReserved="false"/>
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="0"
|
android:defaultValue="0"
|
||||||
|
android:dependency="pref_key_tor_enable"
|
||||||
android:entries="@array/tor_network_setting_names"
|
android:entries="@array/tor_network_setting_names"
|
||||||
android:entryValues="@array/tor_network_setting_values"
|
android:entryValues="@array/tor_network_setting_values"
|
||||||
android:key="pref_key_tor_network"
|
android:key="pref_key_tor_network"
|
||||||
@@ -41,6 +67,7 @@
|
|||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
|
android:dependency="pref_key_tor_enable"
|
||||||
android:key="pref_key_tor_mobile_data"
|
android:key="pref_key_tor_mobile_data"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/tor_mobile_data_title"
|
android:title="@string/tor_mobile_data_title"
|
||||||
@@ -49,6 +76,7 @@
|
|||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
|
android:dependency="pref_key_tor_enable"
|
||||||
android:key="pref_key_tor_only_when_charging"
|
android:key="pref_key_tor_only_when_charging"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/tor_only_when_charging_title"
|
android:title="@string/tor_only_when_charging_title"
|
||||||
|
|||||||
Reference in New Issue
Block a user