Skip to content

Commit

Permalink
Merge pull request #321 from novoda/BOT-320/feature-flags
Browse files Browse the repository at this point in the history
BOT-320/Feature menu
  • Loading branch information
Ryan Feline authored Aug 30, 2017
2 parents d43a56b + edabde1 commit 980ff4e
Show file tree
Hide file tree
Showing 12 changed files with 245 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
import com.novoda.tpbot.controls.ControllerListener;
import com.novoda.tpbot.controls.ControllerView;
import com.novoda.tpbot.controls.ServerDeclarationView;
import com.novoda.tpbot.feature_selection.FeatureSelectionPersistence;
import com.novoda.tpbot.feature_selection.ServerConnectionSharedPreferencesPersistence;
import com.novoda.tpbot.feature_selection.VideoCallSharedPreferencesPersistence;

import java.util.HashMap;

Expand All @@ -45,9 +48,15 @@ public class BotActivity extends AppCompatActivity implements BotView {
private AutomationChecker automationChecker;
private BotServiceCreator botServiceCreator;

private FeatureSelectionPersistence videoCallFeature;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

videoCallFeature = VideoCallSharedPreferencesPersistence.newInstance(this);
FeatureSelectionPersistence serverConnectionFeature = ServerConnectionSharedPreferencesPersistence.newInstance(this);

setContentView(R.layout.activity_bot);

debugView = Views.findById(this, R.id.bot_controller_debug_view);
Expand All @@ -64,12 +73,16 @@ protected void onCreate(Bundle savedInstanceState) {

AccessibilityManager accessibilityManager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
automationChecker = new AutomationChecker(accessibilityManager);

if (!serverConnectionFeature.isFeatureEnabled()) {
switchableView.setDisplayedChild(1);
}
}

@Override
protected void onResume() {
super.onResume();
if (!automationChecker.isHangoutJoinerAutomationServiceEnabled()) {
if (!automationChecker.isHangoutJoinerAutomationServiceEnabled() && videoCallFeature.isFeatureEnabled()) {
startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
}
}
Expand Down Expand Up @@ -205,7 +218,9 @@ public void onConnect(String room, String serverAddress) {
debugView.showPermanently(getString(R.string.connected));
switchableView.setDisplayedChild(1);

joinHangoutRoom(room);
if (videoCallFeature.isFeatureEnabled()) {
joinHangoutRoom(room);
}
}

private void joinHangoutRoom(String room) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import android.os.Handler;
import android.os.Looper;

import com.novoda.tpbot.Direction;
import com.novoda.tpbot.Result;
import com.novoda.support.Observable;
import com.novoda.tpbot.ClientType;
import com.novoda.tpbot.Direction;
import com.novoda.tpbot.Event;
import com.novoda.tpbot.MalformedServerAddressException;
import com.novoda.support.Observable;
import com.novoda.tpbot.Result;
import com.novoda.tpbot.Room;
import com.novoda.tpbot.SocketConnectionObservable;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.novoda.tpbot.feature_selection;

public interface FeatureSelectionController<LIST, FEATURE> {

void attachFeatureSelectionTo(LIST toAttachTo);

void handleFeatureToggle(FEATURE featureRepresentation);

boolean contains(FEATURE featureRepresentation);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.novoda.tpbot.feature_selection;

public interface FeatureSelectionPersistence {

boolean isFeatureEnabled();

void setFeatureEnabled();

void setFeatureDisabled();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.novoda.tpbot.feature_selection;

import android.content.Context;
import android.support.annotation.MenuRes;
import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import com.novoda.tpbot.R;

public final class MenuFeatureSelectionController implements FeatureSelectionController<Menu, MenuItem> {

@MenuRes
private static final int FEATURE_MENU_RESOURCE = R.menu.feature_menu;

private final MenuInflater menuInflater;
private final SparseArray<FeatureSelectionPersistence> features;

public static FeatureSelectionController<Menu, MenuItem> createFrom(Context context) {
MenuInflater menuInflater = new MenuInflater(context);

SparseArray<FeatureSelectionPersistence> features = new SparseArray<>();
features.put(R.id.video_call_menu_item, VideoCallSharedPreferencesPersistence.newInstance(context));
features.put(R.id.server_connection_menu_item, ServerConnectionSharedPreferencesPersistence.newInstance(context));

return new MenuFeatureSelectionController(menuInflater, features);
}

private MenuFeatureSelectionController(MenuInflater menuInflater, SparseArray<FeatureSelectionPersistence> features) {
this.menuInflater = menuInflater;
this.features = features;
}

@Override
public void attachFeatureSelectionTo(Menu toAttachTo) {
menuInflater.inflate(FEATURE_MENU_RESOURCE, toAttachTo);

for (int index = 0; index < features.size(); index++) {
int key = features.keyAt(index);

MenuItem menuItem = toAttachTo.findItem(key);
FeatureSelectionPersistence featureSelectionPersistence = features.get(key);
menuItem.setChecked(featureSelectionPersistence.isFeatureEnabled());
}
}

@Override
public void handleFeatureToggle(MenuItem featureRepresentation) {
FeatureSelectionPersistence featureSelectionPersistence = features.get(featureRepresentation.getItemId());

if (featureSelectionPersistence == null) {
throw new IllegalStateException("You must check if data is present before using handleFeatureToggle().");
}

if (featureSelectionPersistence.isFeatureEnabled()) {
featureRepresentation.setChecked(false);
featureSelectionPersistence.setFeatureDisabled();
} else {
featureRepresentation.setChecked(true);
featureSelectionPersistence.setFeatureEnabled();
}
}

@Override
public boolean contains(MenuItem featureRepresentation) {
return features.get(featureRepresentation.getItemId()) != null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.novoda.tpbot.feature_selection;

import android.content.Context;
import android.content.SharedPreferences;

public final class ServerConnectionSharedPreferencesPersistence implements FeatureSelectionPersistence {

private static final String SERVER_CONNECTION_PREF_NAME = "server_connection";
private static final String SERVER_CONNECTION_PREFERENCES_ON_OFF_KEY = "server_connection_preferences_on_off";
private static final boolean ON = true;
private static final boolean OFF = false;

private final SharedPreferences sharedPreferences;

public static ServerConnectionSharedPreferencesPersistence newInstance(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences(SERVER_CONNECTION_PREF_NAME, Context.MODE_PRIVATE);
return new ServerConnectionSharedPreferencesPersistence(sharedPreferences);
}

private ServerConnectionSharedPreferencesPersistence(SharedPreferences sharedPreferences) {
this.sharedPreferences = sharedPreferences;
}

@Override
public boolean isFeatureEnabled() {
return sharedPreferences.getBoolean(SERVER_CONNECTION_PREFERENCES_ON_OFF_KEY, OFF);
}

@Override
public void setFeatureEnabled() {
sharedPreferences.edit()
.putBoolean(SERVER_CONNECTION_PREFERENCES_ON_OFF_KEY, ON)
.apply();
}

@Override
public void setFeatureDisabled() {
sharedPreferences.edit()
.putBoolean(SERVER_CONNECTION_PREFERENCES_ON_OFF_KEY, OFF)
.apply();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.novoda.tpbot.feature_selection;

import android.content.Context;
import android.content.SharedPreferences;

public final class VideoCallSharedPreferencesPersistence implements FeatureSelectionPersistence {

private static final String VIDEO_CALL_PREF_NAME = "video_call";
private static final String VIDEO_CALL_PREFERENCES_ON_OFF_KEY = "video_call_preferences_on_off";
private static final boolean ON = true;
private static final boolean OFF = false;

private final SharedPreferences sharedPreferences;

public static VideoCallSharedPreferencesPersistence newInstance(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences(VIDEO_CALL_PREF_NAME, Context.MODE_PRIVATE);
return new VideoCallSharedPreferencesPersistence(sharedPreferences);
}

private VideoCallSharedPreferencesPersistence(SharedPreferences sharedPreferences) {
this.sharedPreferences = sharedPreferences;
}

@Override
public boolean isFeatureEnabled() {
return sharedPreferences.getBoolean(VIDEO_CALL_PREFERENCES_ON_OFF_KEY, OFF);
}

@Override
public void setFeatureEnabled() {
sharedPreferences.edit()
.putBoolean(VIDEO_CALL_PREFERENCES_ON_OFF_KEY, ON)
.apply();
}

@Override
public void setFeatureDisabled() {
sharedPreferences.edit()
.putBoolean(VIDEO_CALL_PREFERENCES_ON_OFF_KEY, OFF)
.apply();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ protected void onCreate(Bundle savedInstanceState) {
ServerDeclarationView serverDeclarationView = Views.findById(switchableView, R.id.bot_server_declaration_view);
serverDeclarationView.setServerDeclarationListener(serverDeclarationListener);


}

private final CommandRepeater.Listener commandRepeatedListener = new CommandRepeater.Listener() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import android.os.Handler;
import android.os.Looper;

import com.novoda.tpbot.Direction;
import com.novoda.tpbot.Result;
import com.novoda.support.Observable;
import com.novoda.tpbot.ClientType;
import com.novoda.tpbot.Direction;
import com.novoda.tpbot.Event;
import com.novoda.tpbot.MalformedServerAddressException;
import com.novoda.support.Observable;
import com.novoda.tpbot.Result;
import com.novoda.tpbot.Room;
import com.novoda.tpbot.SocketConnectionObservable;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import com.novoda.tpbot.R;
import com.novoda.tpbot.bot.BotActivity;
import com.novoda.tpbot.feature_selection.FeatureSelectionController;
import com.novoda.tpbot.feature_selection.MenuFeatureSelectionController;
import com.novoda.tpbot.human.HumanActivity;

public class LandingActivity extends AppCompatActivity {

private FeatureSelectionController<Menu, MenuItem> featureSelectionController;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
featureSelectionController = MenuFeatureSelectionController.createFrom(this);

setContentView(R.layout.activity_landing);

View humanSelection = findViewById(R.id.human_selection);
Expand All @@ -39,4 +47,19 @@ public void onClick(View v) {
}
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
featureSelectionController.attachFeatureSelectionTo(menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (featureSelectionController.contains(item)) {
featureSelectionController.handleFeatureToggle(item);
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
}
19 changes: 19 additions & 0 deletions TelepresenceBot/mobile/src/main/res/menu/feature_menu.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<item
android:id="@+id/video_call_menu_item"
android:icon="@android:drawable/checkbox_on_background"
android:title="@string/automatically_join_video_call"
android:checkable="true"
app:showAsAction="never" />

<item
android:id="@+id/server_connection_menu_item"
android:icon="@android:drawable/checkbox_on_background"
android:title="@string/connect_to_server"
android:checkable="true"
app:showAsAction="never" />

</menu>
2 changes: 2 additions & 0 deletions TelepresenceBot/mobile/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<string name="bot">Bot</string>
<string name="human">Human</string>
<string name="list_connected_devices_menu_item_title">List connected devices</string>
<string name="automatically_join_video_call">Automatically join video call</string>
<string name="connect_to_server">Connect to server</string>
<string name="usb_device_name_vendor_product">%1$s, VendorId=%2$d, ProductId=%3$d</string>
<string name="no_connected_devices">No connected USB devices</string>
<string name="enter_server_address">Enter server address: </string>
Expand Down

0 comments on commit 980ff4e

Please sign in to comment.