Commit 15079791 authored by cyberta's avatar cyberta
Browse files

implement basic UI update mechanism to start / stop the VPN and to react on VPN state changes

parent 7f20f030
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
    package="org.torproject.artitoyvpn">

    <application
        android:name=".ArtiToyVPNApp"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
+15 −0
Original line number Diff line number Diff line
package org.torproject.artitoyvpn;

import android.app.Application;

import org.torproject.artitoyvpn.vpn.VpnStatusObservable;

public class ArtiToyVPNApp extends Application {

    VpnStatusObservable vpnStatusObservable;
    @Override
    public void onCreate() {
        super.onCreate();
        vpnStatusObservable = VpnStatusObservable.getInstance();
    }
}
+32 −3
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import androidx.annotation.NonNull;
@@ -14,6 +15,12 @@ import androidx.lifecycle.ViewModelProvider;

import org.torproject.artitoyvpn.R;
import org.torproject.artitoyvpn.databinding.FragmentHomeBinding;
import org.torproject.artitoyvpn.utils.Utils;
import org.torproject.artitoyvpn.vpn.VpnStatusObservable;
import org.torproject.artitoyvpn.vpn.VpnStatusObservable.Status;

import java.util.Timer;
import java.util.TimerTask;

public class HomeFragment extends Fragment {

@@ -29,15 +36,37 @@ public class HomeFragment extends Fragment {
        View root = binding.getRoot();

        final TextView textView = binding.textVpnState;
        homeViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
        homeViewModel.getText().observe(getViewLifecycleOwner(), s -> textView.setText(s));

        final Button vpnButton = binding.buttonMain;
        VpnStatusObservable.getStatus().observe(getViewLifecycleOwner(), status -> homeViewModel.update(status, getContext()));
        homeViewModel.getButtonText().observe(getViewLifecycleOwner(), text -> vpnButton.setText(text));
        homeViewModel.isButtonEnabled().observe(getViewLifecycleOwner(), enabled -> vpnButton.setEnabled(enabled));

        vpnButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onChanged(@Nullable String s) {
                textView.setText(s);
            public void onClick(View view) {
                // TODO: start/stop VPN here
                Status status = VpnStatusObservable.getStatus().getValue();
                if (status == Status.RUNNING) {
                    VpnStatusObservable.update(Status.STOPPING);
                    Utils.runWithDelay(1000, () -> VpnStatusObservable.update(Status.STOPPED));
                } else if (status == Status.STOPPED) {
                    VpnStatusObservable.update(Status.STARTING);
                    Utils.runWithDelay(1000, () -> VpnStatusObservable.update(Status.RUNNING));
                }
            }
        });
        return root;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        homeViewModel.stateText.setValue(getContext().getString(R.string.state_description_off));
        homeViewModel.buttonText.setValue(getContext().getString(R.string.start));
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
+52 −4
Original line number Diff line number Diff line
package org.torproject.artitoyvpn.ui.home;

import android.content.Context;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import org.torproject.artitoyvpn.R;
import org.torproject.artitoyvpn.vpn.VpnStatusObservable;

public class HomeViewModel extends ViewModel {

    private MutableLiveData<String> mText;
    final MutableLiveData<String> stateText;
    final MutableLiveData<String> buttonText;
    final MutableLiveData<Boolean> isButtonEnabled;

    public HomeViewModel() {
        mText = new MutableLiveData<>();
        mText.setValue("This is the home fragment");
        super();
        stateText = new MutableLiveData<>();
        buttonText = new MutableLiveData<>();
        isButtonEnabled = new MutableLiveData<>();
    }

    public LiveData<String> getText() {
        return mText;
        return stateText;
    }

    public LiveData<String> getButtonText() {
        return buttonText;
    }

    public LiveData<Boolean> isButtonEnabled() {
        return isButtonEnabled;
    }


    public void update(VpnStatusObservable.Status status, Context context) {
        switch (status) {
            case STARTING:
                stateText.postValue(context.getString(R.string.state_description_starting));
                buttonText.postValue(context.getString(R.string.stop));
                isButtonEnabled.postValue(false);
                break;
            case RUNNING:
                stateText.postValue(context.getString(R.string.state_description_running));
                buttonText.postValue(context.getString(R.string.stop));
                isButtonEnabled.postValue(true);
                break;
            case STOPPING:
                stateText.postValue(context.getString(R.string.state_description_stopping));
                buttonText.postValue(context.getString(R.string.stop));
                isButtonEnabled.postValue(false);
                break;
            case STOPPED:
                stateText.postValue(context.getString(R.string.state_description_off));
                buttonText.postValue(context.getString(R.string.start));
                isButtonEnabled.postValue(true);
                break;
            case ERROR:
                stateText.postValue(context.getString(R.string.state_description_error));
                buttonText.postValue(context.getString(R.string.stop));
                isButtonEnabled.postValue(true);
                break;
        }
    }
}
 No newline at end of file
+22 −0
Original line number Diff line number Diff line
package org.torproject.artitoyvpn.utils;

import android.os.Looper;

import java.util.Timer;
import java.util.TimerTask;

public class Utils {
    public static boolean isRunningOnMainThread() {
        return Looper.getMainLooper().getThread() == Thread.currentThread();
    }


    public static void runWithDelay(long delay, Runnable runnable) {
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                runnable.run();
            }
        }, delay);
    }
}
Loading