diff --git a/ui/src/main/java/com/wireguard/android/Application.kt b/ui/src/main/java/com/wireguard/android/Application.kt index 7697157..be25848 100644 --- a/ui/src/main/java/com/wireguard/android/Application.kt +++ b/ui/src/main/java/com/wireguard/android/Application.kt @@ -60,7 +60,6 @@ class Application : android.app.Application(), OnSharedPreferenceChangeListener override fun onCreate() { Log.i(TAG, USER_AGENT) super.onCreate() - DataRepository.buildRepositoryInstance() asyncWorker = AsyncWorker(AsyncTask.SERIAL_EXECUTOR, Handler(Looper.getMainLooper())) rootShell = RootShell(applicationContext) toolsInstaller = ToolsInstaller(applicationContext, rootShell) diff --git a/ui/src/main/java/com/wireguard/android/activity/LoginActivity.java b/ui/src/main/java/com/wireguard/android/activity/LoginActivity.java index b9f994a..97bc0ed 100644 --- a/ui/src/main/java/com/wireguard/android/activity/LoginActivity.java +++ b/ui/src/main/java/com/wireguard/android/activity/LoginActivity.java @@ -1,10 +1,12 @@ package com.wireguard.android.activity; +import androidx.annotation.Nullable; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import android.content.Intent; import android.os.Bundle; +import android.security.KeyChain; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; @@ -14,9 +16,14 @@ import android.widget.Toast; import com.wireguard.android.R; import com.wireguard.android.model.User; +import com.wireguard.android.repository.DataRepository; import com.wireguard.android.resource.StatusResource; import com.wireguard.android.viewmodel.LoginViewModel; +import javax.security.cert.CertificateEncodingException; +import javax.security.cert.CertificateException; +import javax.security.cert.X509Certificate; + public class LoginActivity extends BaseActivityBubble { private LoginViewModel loginViewModel; @@ -25,6 +32,12 @@ public class LoginActivity extends BaseActivityBubble { private EditText password; private Button sign; + private static final String BASE_URL_PREFIX = "https://"; + private static final String BASE_URL_SUFFIX = ":1443/api/"; + private static final String SEPARATOR = "\\."; + private static final int REQUEST_CODE = 1555; + private static final String CERTIFICATE_NAME = "Bubble Certificate"; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -41,11 +54,21 @@ public class LoginActivity extends BaseActivityBubble { private void initListeners() { sign.setOnClickListener(new OnClickListener() { @Override public void onClick(final View v) { - final String tunnelName = bubbleName.getText().toString().trim(); - final String username = userName.getText().toString().trim(); - final String password = LoginActivity.this.password.getText().toString().trim(); + final String url = BASE_URL_PREFIX + bubbleName.getText().toString() + BASE_URL_SUFFIX; + if (url.split(SEPARATOR).length != 3) { + Toast.makeText(LoginActivity.this, getResources().getText(R.string.hostname_not_valid), Toast.LENGTH_LONG).show(); + return; + } + if (DataRepository.getRepositoryInstance() == null) { + loginViewModel.buildRepositoryInstance(LoginActivity.this, url); + } else { + loginViewModel.buildClientService(url); + } + loginViewModel.setUserURL(LoginActivity.this, url); + final String usernameInput = userName.getText().toString().trim(); + final String passwordInput = password.getText().toString().trim(); showLoadingDialog(); - login(tunnelName, username, password); + login(usernameInput, passwordInput); } }); } @@ -57,28 +80,48 @@ public class LoginActivity extends BaseActivityBubble { sign = findViewById(R.id.signButton); } - private void login(String tunnelName, String username, String password) { - loginViewModel.login(tunnelName, username, password, this).observe(this, new Observer>() { + private void login(String username, String password) { + loginViewModel.login(username, password, this).observe(this, new Observer>() { @Override public void onChanged(final StatusResource userStatusResource) { switch (userStatusResource.status) { case SUCCESS: - Toast.makeText(LoginActivity.this, "Success", Toast.LENGTH_SHORT).show(); - Log.d("TAG", "Success"); - closeLoadingDialog(); - Intent intent = new Intent(LoginActivity.this, MainActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - startActivity(intent); + loginViewModel.getCertificate(LoginActivity.this).observe(LoginActivity.this, new Observer() { + @Override public void onChanged(final byte[] encodedCertificate) { + closeLoadingDialog(); + if (encodedCertificate.length == 0) { + Toast.makeText(LoginActivity.this, getString(R.string.failed_bubble), Toast.LENGTH_SHORT).show(); + } else { + final Intent intent = KeyChain.createInstallIntent(); + intent.putExtra(KeyChain.EXTRA_CERTIFICATE, encodedCertificate); + intent.putExtra(KeyChain.EXTRA_NAME, CERTIFICATE_NAME); + startActivityForResult(intent, REQUEST_CODE); + } + } + }); break; case LOADING: Log.d("TAG", "Loading"); break; case ERROR: closeLoadingDialog(); - Toast.makeText(LoginActivity.this, "Login Failed", Toast.LENGTH_SHORT).show(); + Toast.makeText(LoginActivity.this, getString(R.string.login_failed), Toast.LENGTH_SHORT).show(); Log.d("TAG", "Error"); break; } } }); } + + @Override protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) { + Toast.makeText(this, getString(R.string.success), Toast.LENGTH_SHORT).show(); + Log.d("TAG", "Success"); + final Intent mainActivityIntent = new Intent(this, MainActivity.class); + mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(mainActivityIntent); + } else { + Toast.makeText(this, getString(R.string.cerificate_install), Toast.LENGTH_LONG).show(); + } + } } diff --git a/ui/src/main/java/com/wireguard/android/activity/MainActivity.java b/ui/src/main/java/com/wireguard/android/activity/MainActivity.java index 983eafb..71a70d4 100644 --- a/ui/src/main/java/com/wireguard/android/activity/MainActivity.java +++ b/ui/src/main/java/com/wireguard/android/activity/MainActivity.java @@ -2,6 +2,7 @@ package com.wireguard.android.activity; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; +import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import android.content.Intent; import android.os.Bundle; @@ -9,22 +10,14 @@ import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; -import android.widget.Toast; - -import com.wireguard.android.Application; import com.wireguard.android.R; -import com.wireguard.android.backend.GoBackend; -import com.wireguard.android.backend.Tunnel; -import com.wireguard.android.model.ObservableTunnel; import com.wireguard.android.viewmodel.MainViewModel; public class MainActivity extends AppCompatActivity { private MainViewModel mainViewModel; private TextView bubbleStatus; - private TextView deviceStatus; private Button connectButton; - public ObservableTunnel pendingTunnel; - private Boolean pendingTunnelUp; + private boolean connectionStateFlag; private static final int REQUEST_CODE_VPN_PERMISSION = 23491; @@ -39,8 +32,19 @@ public class MainActivity extends AppCompatActivity { startActivity(intent); finish(); } + mainViewModel.buildRepositoryInstance(this, mainViewModel.getUserURL(this)); initUI(); - pendingTunnel = mainViewModel.getTunnel(this); + } + + @Override protected void onResume() { + super.onResume(); + if (mainViewModel.isVPNConnected(this, connectionStateFlag)) { + connectionStateFlag = false; + setConnectionStateUI(false); + } else { + connectionStateFlag = true; + setConnectionStateUI(true); + } } private void initUI() { @@ -50,7 +54,6 @@ public class MainActivity extends AppCompatActivity { private void initViews() { bubbleStatus = findViewById(R.id.bubbleStatus); - deviceStatus = findViewById(R.id.deviceStatus); connectButton = findViewById(R.id.connectButton); } @@ -63,44 +66,39 @@ public class MainActivity extends AppCompatActivity { } private void connect() { - setTunnelState(true); - } - - private void setTunnelState(final Boolean checked) { - if(pendingTunnel!=null) { - final ObservableTunnel tunnel = pendingTunnel; - Application.getBackendAsync().thenAccept(backend -> { - if (backend instanceof GoBackend) { - final Intent intent = GoBackend.VpnService.prepare(this); - if (intent != null) { - pendingTunnelUp = checked; - startActivityForResult(intent, REQUEST_CODE_VPN_PERMISSION); - return; - } - } - setTunnelStateWithPermissionsResult(tunnel, checked); - }); - } - -} - - private void setTunnelStateWithPermissionsResult(final ObservableTunnel tunnel, final boolean checked) { - tunnel.setStateAsync(Tunnel.State.of(checked)).whenComplete((observableTunnel, throwable) ->{ - if(throwable==null){ - Toast.makeText(this,"Connected",Toast.LENGTH_SHORT).show(); - } - else { - Toast.makeText(this,"Failed",Toast.LENGTH_SHORT).show(); - } + final boolean state = mainViewModel.isVPNConnected(this, connectionStateFlag); + connectionStateFlag = state; + mainViewModel.connect(state, MainActivity.this).observe(MainActivity.this, new Observer() { + @Override public void onChanged(final Boolean state) { + setConnectionStateUI(state); + } }); } @Override protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_VPN_PERMISSION) { - if (pendingTunnel != null && pendingTunnelUp != null) setTunnelStateWithPermissionsResult(pendingTunnel, pendingTunnelUp); - pendingTunnel = null; - pendingTunnelUp = null; + if (resultCode == RESULT_OK) { + mainViewModel.connectWithPermission(connectionStateFlag, this) + .observe(this, new Observer() { + @Override public void onChanged(final Boolean state) { + setConnectionStateUI(state); + } + }); + } else { + connectionStateFlag = false; + setConnectionStateUI(false); + } + } + } + + private void setConnectionStateUI(boolean state) { + if (state) { + bubbleStatus.setText(getString(R.string.connected_bubble)); + connectButton.setText(getString(R.string.disconnect)); + } else { + bubbleStatus.setText(getString(R.string.not_connected_bubble)); + connectButton.setText(getString(R.string.connect)); } } } diff --git a/ui/src/main/java/com/wireguard/android/api/ApiConstants.java b/ui/src/main/java/com/wireguard/android/api/ApiConstants.java index 715ce9f..4b4665b 100644 --- a/ui/src/main/java/com/wireguard/android/api/ApiConstants.java +++ b/ui/src/main/java/com/wireguard/android/api/ApiConstants.java @@ -1,7 +1,6 @@ package com.wireguard.android.api; public class ApiConstants { - public static final String BASE_URL = "https://jtest2.bubblesecure.com:1443/api/"; public static final String LOGIN_URL = "auth/login"; public static final String ALL_DEVICES_URL = "me/devices"; public static final String ADD_DEVICE_URL = "me/devices"; @@ -12,4 +11,5 @@ public class ApiConstants { public static final String AUTHORIZATION_HEADER = "X-Bubble-Session"; public static final String DEVICE_NAME = "name"; public static final String DEVICE_TYPE = "deviceType"; + public static final String CERTIFICATE_URL = "auth/cacert?deviceType=android"; } diff --git a/ui/src/main/java/com/wireguard/android/api/network/ClientService.java b/ui/src/main/java/com/wireguard/android/api/network/ClientService.java index 2b2b419..5ebf9bc 100644 --- a/ui/src/main/java/com/wireguard/android/api/network/ClientService.java +++ b/ui/src/main/java/com/wireguard/android/api/network/ClientService.java @@ -28,7 +28,7 @@ public class ClientService { } - public ClientApi createClientApi() { + public ClientApi createClientApi(String url) { OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); @@ -40,7 +40,7 @@ public class ClientService { httpClient.addInterceptor(new UserAgentInterceptor(System.getProperty("http.agent"))); return new Retrofit.Builder() - .baseUrl(ApiConstants.BASE_URL) + .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(httpClient.build()) diff --git a/ui/src/main/java/com/wireguard/android/repository/DataRepository.java b/ui/src/main/java/com/wireguard/android/repository/DataRepository.java index 6f7a2a7..9431ac4 100644 --- a/ui/src/main/java/com/wireguard/android/repository/DataRepository.java +++ b/ui/src/main/java/com/wireguard/android/repository/DataRepository.java @@ -1,15 +1,21 @@ package com.wireguard.android.repository; import android.content.Context; +import android.content.Intent; import android.os.Build; import android.provider.Settings; import android.provider.Settings.Secure; +import android.widget.Toast; import com.wireguard.android.Application; +import com.wireguard.android.R; +import com.wireguard.android.activity.MainActivity; import com.wireguard.android.api.ApiConstants; import com.wireguard.android.api.network.ClientApi; import com.wireguard.android.api.network.ClientService; import com.wireguard.android.api.network.NetworkBoundStatusResource; +import com.wireguard.android.backend.GoBackend; +import com.wireguard.android.backend.Tunnel; import com.wireguard.android.backend.Tunnel.State; import com.wireguard.android.configStore.FileConfigStore; import com.wireguard.android.model.Device; @@ -30,7 +36,13 @@ import java.util.HashMap; import java.util.List; import java.util.Scanner; +import javax.security.cert.CertificateEncodingException; +import javax.security.cert.CertificateException; +import javax.security.cert.X509Certificate; + +import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; @@ -46,33 +58,45 @@ public class DataRepository { private ClientApi clientApi; private CompositeDisposable compositeDisposable; private final OkHttpClient client = new OkHttpClient(); + private TunnelManager tunnelManager; + private ObservableTunnel pendingTunnel; public static final String NO_INTERNET_CONNECTION = "no_internet_connection"; private static final String SEPARATOR = ":"; private static final String SPACE = " "; private static final String DELIMITER = "\\A"; private static final int ANDROID_ID = 1; + private static String BASE_URL = ""; + private static final String TUNNEL_NAME = "BubbleVPN"; + private static final int REQUEST_CODE_VPN_PERMISSION = 23491; - private DataRepository() { - clientApi = ClientService.getInstance().createClientApi(); + private DataRepository(Context context, String url) { + BASE_URL = url; + clientApi = ClientService.getInstance().createClientApi(url); compositeDisposable = new CompositeDisposable(); + tunnelManager = new TunnelManager(new FileConfigStore(context)); } - public static void buildRepositoryInstance() { + public static void buildRepositoryInstance(Context context, String url) { if (instance == null) { synchronized (DataRepository.class) { if (instance == null) { - instance = new DataRepository(); + instance = new DataRepository(context, url); } } } } + public void buildClientService(String url) { + BASE_URL = url; + clientApi = ClientService.getInstance().createClientApi(url); + } + public static DataRepository getRepositoryInstance() { return instance; } - public MutableLiveData> login(String tunnelName, String username, String password, Context context) { + public MutableLiveData> login(String username, String password, Context context) { return new NetworkBoundStatusResource() { @Override protected void createCall() { @@ -115,7 +139,7 @@ public class DataRepository { addDevice(context); } }, throwable -> { - + setMutableLiveData(StatusResource.error(throwable.getMessage())); }); compositeDisposable.add(disposableAllDevices); } @@ -223,7 +247,7 @@ public class DataRepository { final String deviceID = UserStore.getInstance(context).getDeviceID(); final String token = UserStore.getInstance(context).getToken(); Request request = new Request.Builder() - .url(ApiConstants.BASE_URL + ApiConstants.CONFIG_DEVICE_URL + deviceID + ApiConstants.CONFIG_VPN_URL) + .url(BASE_URL + ApiConstants.CONFIG_DEVICE_URL + deviceID + ApiConstants.CONFIG_VPN_URL) .addHeader(ApiConstants.AUTHORIZATION_HEADER, token) .build(); client.newCall(request).enqueue(new Callback() { @@ -235,18 +259,19 @@ public class DataRepository { final InputStream inputStream = response.body().byteStream(); final Scanner scanner = new Scanner(inputStream).useDelimiter(DELIMITER); final String data = scanner.hasNext() ? scanner.next() : ""; - createTunnel(data, tunnelName); + createTunnel(data); } }); } - private void createTunnel(String rawConfig, String tunnelName) { + private void createTunnel(final String rawConfig) { try { final byte[] configBytes = rawConfig.getBytes(); final Config config = Config.parse(new ByteArrayInputStream(configBytes)); - Application.getTunnelManager().create(tunnelName, config).whenComplete((observableTunnel, throwable) -> { + Application.getTunnelManager().create(TUNNEL_NAME, config).whenComplete((observableTunnel, throwable) -> { if (observableTunnel != null) { - TunnelStore.getInstance(context).setTunnel(tunnelName, rawConfig); + TunnelStore.getInstance(context).setTunnel(TUNNEL_NAME, rawConfig); + tunnelManager.setTunnelState(observableTunnel, State.DOWN); setMutableLiveData(StatusResource.success()); } else { setMutableLiveData(StatusResource.error(throwable.getMessage())); @@ -300,7 +325,14 @@ public class DataRepository { } - public ObservableTunnel getTunnel(Context context) { + private Config parseConfig(String data) throws IOException, BadConfigException { + final byte[] configText = data.getBytes(); + final Config config = Config.parse(new ByteArrayInputStream(configText)); + return config; + } + + + private ObservableTunnel createTunnel(final Context context, final boolean stateTunnel) { //TODO implement config is null case Config config = null; try { @@ -309,14 +341,107 @@ public class DataRepository { return null; } final String name = TunnelStore.getInstance(context).getTunnelName(); - final TunnelManager tunnelManager = new TunnelManager(new FileConfigStore(context)); - final ObservableTunnel tunnel = new ObservableTunnel(tunnelManager, name, config, State.DOWN); + final ObservableTunnel tunnel; + if (stateTunnel) { + tunnel = new ObservableTunnel(tunnelManager, name, config, State.UP); + } else { + tunnel = new ObservableTunnel(tunnelManager, name, config, State.DOWN); + } + tunnelManager.setTunnelState(tunnel, tunnel.getState()); + return tunnel; } - private Config parseConfig(String data) throws IOException, BadConfigException { - final byte[] configText = data.getBytes(); - final Config config = Config.parse(new ByteArrayInputStream(configText)); - return config; + public void setUserURL(Context context, String url) { + UserStore.getInstance(context).setUserURL(url); + } + + public ObservableTunnel getTunnel(Context context, boolean connectionStateFlag) { + ObservableTunnel tunnel = tunnelManager.getLastUsedTunnel(); + if (tunnel == null) { + tunnel = createTunnel(context, connectionStateFlag); + } + return tunnel; + } + + public MutableLiveData getCertificate(Context context) { + final MutableLiveData liveData = new MutableLiveData<>(); + final Request request = new Request.Builder() + .url(BASE_URL + ApiConstants.CERTIFICATE_URL) + .build(); + client.newCall(request).enqueue(new Callback() { + @Override public void onFailure(final okhttp3.Call call, final IOException e) { + liveData.postValue(new byte[]{}); + } + + @Override public void onResponse(final okhttp3.Call call, final Response response) throws IOException { + if (response.isSuccessful()) { + final InputStream inputStream = response.body().byteStream(); + final Scanner scanner = new Scanner(inputStream).useDelimiter(DELIMITER); + final String data = scanner.hasNext() ? scanner.next() : ""; + final byte[] cert = data.getBytes(); + X509Certificate x509Certificate = null; + try { + x509Certificate = X509Certificate.getInstance(cert); + } catch (final CertificateException e) { + liveData.postValue(new byte[]{}); + } + try { + liveData.postValue(x509Certificate.getEncoded()); + } catch (final CertificateEncodingException e) { + liveData.postValue(new byte[]{}); + } + } else { + liveData.postValue(new byte[]{}); + } + } + }); + return liveData; + } + + public boolean isVPNConnected(Context context, boolean connectionStateFlag) { + pendingTunnel = getTunnel(context, connectionStateFlag); + return pendingTunnel.getState() == State.DOWN; + } + + public MutableLiveData connect(final Boolean checked , Context context) { + MutableLiveData liveData = new MutableLiveData<>(); + if (pendingTunnel != null) { + Application.getBackendAsync().thenAccept(backend -> { + if (backend instanceof GoBackend) { + final Intent intent = GoBackend.VpnService.prepare(context); + if (intent != null) { + if(context instanceof MainActivity) { + ((MainActivity)context).startActivityForResult(intent, REQUEST_CODE_VPN_PERMISSION); + return; + } + } + } + connectWithPermission(checked,context).observe((LifecycleOwner) context, new Observer() { + @Override public void onChanged(final Boolean aBoolean) { + liveData.postValue(aBoolean); + } + }); + }); + } + return liveData; + } + + public MutableLiveData connectWithPermission(final boolean checked , Context context) { + MutableLiveData liveData = new MutableLiveData<>(); + pendingTunnel.setStateAsync(Tunnel.State.of(checked)).whenComplete((observableTunnel, throwable) ->{ + if(throwable==null){ + if(observableTunnel == State.DOWN) { + liveData.postValue(false); + } + else { + liveData.postValue(true); + } + } + else { + Toast.makeText(context,context.getString(R.string.failed_bubble),Toast.LENGTH_SHORT).show(); + } + }); + return liveData; } } diff --git a/ui/src/main/java/com/wireguard/android/util/UserStore.java b/ui/src/main/java/com/wireguard/android/util/UserStore.java index 58eac38..ee46734 100644 --- a/ui/src/main/java/com/wireguard/android/util/UserStore.java +++ b/ui/src/main/java/com/wireguard/android/util/UserStore.java @@ -11,9 +11,11 @@ public class UserStore { private static final String USER_DATA_KEY = "com.wireguard.android.util.bubbleUserResponse"; private static final String DEVICE_DATA_KEY = "com.wireguard.android.util.bubbleDeviceResponse"; private static final String DEVICE_ID_KEY = "com.wireguard.android.util.bubbleDeviceIDResponse"; + private static final String USER_BASE_URL_KEY = "com.wireguard.android.util.bubbleUserURLResponse"; public static final String USER_TOKEN_DEFAULT_VALUE = ""; public static final String DEVICE_DEFAULT_VALUE = ""; public static final String DEVICE_ID_DEFAULT_VALUE = ""; + public static final String USER_BASE_URL_DEFAULT_VALUE = ""; public static UserStore getInstance(Context context) { if (instance == null) { @@ -51,4 +53,12 @@ public class UserStore { public String getDeviceID(){ return sharedPreferences.getString(DEVICE_ID_KEY,DEVICE_ID_DEFAULT_VALUE); } + + public void setUserURL(String url){ + sharedPreferences.edit().putString(USER_BASE_URL_KEY,url).apply(); + } + + public String getUserURL(){ + return sharedPreferences.getString(USER_BASE_URL_KEY,USER_BASE_URL_DEFAULT_VALUE); + } } diff --git a/ui/src/main/java/com/wireguard/android/viewmodel/LoginViewModel.java b/ui/src/main/java/com/wireguard/android/viewmodel/LoginViewModel.java index 8b21efb..43728a8 100644 --- a/ui/src/main/java/com/wireguard/android/viewmodel/LoginViewModel.java +++ b/ui/src/main/java/com/wireguard/android/viewmodel/LoginViewModel.java @@ -5,17 +5,35 @@ import android.content.Context; import com.wireguard.android.model.User; import com.wireguard.android.repository.DataRepository; import com.wireguard.android.resource.StatusResource; +import com.wireguard.android.util.UserStore; import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; public class LoginViewModel extends ViewModel { - public LiveData> login(String tunnelName, String username, String password, Context context) { - return DataRepository.getRepositoryInstance().login(tunnelName,username, password, context); + public LiveData> login(String username, String password, Context context) { + return DataRepository.getRepositoryInstance().login(username, password, context); } @Override protected void onCleared() { super.onCleared(); DataRepository.getRepositoryInstance().clearDisposable(); } + + public void buildRepositoryInstance(Context context, String url){ + DataRepository.buildRepositoryInstance(context,url); + } + + public void setUserURL(Context context, String url){ + DataRepository.getRepositoryInstance().setUserURL(context,url); + } + + public void buildClientService(String url){ + DataRepository.getRepositoryInstance().buildClientService(url); + } + + public MutableLiveData getCertificate(Context context){ + return DataRepository.getRepositoryInstance().getCertificate(context); + } } diff --git a/ui/src/main/java/com/wireguard/android/viewmodel/MainViewModel.java b/ui/src/main/java/com/wireguard/android/viewmodel/MainViewModel.java index 738de9b..c4285cd 100644 --- a/ui/src/main/java/com/wireguard/android/viewmodel/MainViewModel.java +++ b/ui/src/main/java/com/wireguard/android/viewmodel/MainViewModel.java @@ -3,15 +3,40 @@ package com.wireguard.android.viewmodel; import android.content.Context; import com.wireguard.android.model.ObservableTunnel; +import com.wireguard.android.model.TunnelManager; import com.wireguard.android.repository.DataRepository; +import com.wireguard.android.util.TunnelStore; +import com.wireguard.android.util.UserStore; + +import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; public class MainViewModel extends ViewModel { public boolean isUserLoggedIn(Context context){ - return DataRepository.getRepositoryInstance().isUserLoggedIn(context); + return !UserStore.USER_TOKEN_DEFAULT_VALUE.equals(UserStore.getInstance(context).getToken()); + } + + public ObservableTunnel getTunnel(Context context, boolean stateTunnel) { + return DataRepository.getRepositoryInstance().getTunnel(context,stateTunnel); + } + + public void buildRepositoryInstance(Context context, String url){ + DataRepository.buildRepositoryInstance(context,url); + } + + public String getUserURL(Context context){ + return UserStore.getInstance(context).getUserURL(); + } + + public MutableLiveData connectWithPermission(final boolean checked , Context context) { + return DataRepository.getRepositoryInstance().connectWithPermission(checked,context); + } + + public MutableLiveData connect(final Boolean checked , Context context) { + return DataRepository.getRepositoryInstance().connect(checked,context); } - public ObservableTunnel getTunnel(Context context) { - return DataRepository.getRepositoryInstance().getTunnel(context); + public boolean isVPNConnected(Context context, boolean connectionStateFlag) { + return DataRepository.getRepositoryInstance().isVPNConnected(context,connectionStateFlag); } } diff --git a/ui/src/main/res/layout/activity_main.xml b/ui/src/main/res/layout/activity_main.xml index ffbbcc1..3986311 100644 --- a/ui/src/main/res/layout/activity_main.xml +++ b/ui/src/main/res/layout/activity_main.xml @@ -35,40 +35,15 @@ android:id="@+id/bubbleStatus" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/running" + android:text="@string/not_connected_bubble" android:textSize="20sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.565" + app:layout_constraintHorizontal_bias="0.75" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.183" /> - - - -