Update SyncManager

pull/286/head
Alinson S. Xavier 9 years ago
parent 08e3c9cc40
commit 3da996b8a4

@ -25,7 +25,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
} }
debug { debug {
testCoverageEnabled = true testCoverageEnabled = false
} }
} }

@ -29,6 +29,7 @@ import org.isoron.uhabits.models.*;
import org.isoron.uhabits.models.sqlite.*; import org.isoron.uhabits.models.sqlite.*;
import org.isoron.uhabits.notifications.*; import org.isoron.uhabits.notifications.*;
import org.isoron.uhabits.preferences.*; import org.isoron.uhabits.preferences.*;
import org.isoron.uhabits.sync.*;
import org.isoron.uhabits.tasks.*; import org.isoron.uhabits.tasks.*;
import org.isoron.uhabits.utils.*; import org.isoron.uhabits.utils.*;
import org.isoron.uhabits.widgets.*; import org.isoron.uhabits.widgets.*;
@ -74,6 +75,8 @@ public interface AppComponent
ReminderScheduler getReminderScheduler(); ReminderScheduler getReminderScheduler();
SyncManager getSyncManager();
TaskRunner getTaskRunner(); TaskRunner getTaskRunner();
WidgetPreferences getWidgetPreferences(); WidgetPreferences getWidgetPreferences();

@ -25,6 +25,7 @@ import org.isoron.uhabits.*;
import org.isoron.uhabits.activities.*; import org.isoron.uhabits.activities.*;
import org.isoron.uhabits.activities.habits.list.model.*; import org.isoron.uhabits.activities.habits.list.model.*;
import org.isoron.uhabits.preferences.*; import org.isoron.uhabits.preferences.*;
import org.isoron.uhabits.sync.*;
import org.isoron.uhabits.utils.*; import org.isoron.uhabits.utils.*;
/** /**
@ -46,6 +47,8 @@ public class ListHabitsActivity extends BaseActivity
private MidnightTimer midnightTimer; private MidnightTimer midnightTimer;
private SyncManager syncManager;
public ListHabitsComponent getListHabitsComponent() public ListHabitsComponent getListHabitsComponent()
{ {
return component; return component;
@ -81,6 +84,7 @@ public class ListHabitsActivity extends BaseActivity
rootView.setController(controller, selectionMenu); rootView.setController(controller, selectionMenu);
midnightTimer = component.getMidnightTimer(); midnightTimer = component.getMidnightTimer();
syncManager = app.getComponent().getSyncManager();
setScreen(screen); setScreen(screen);
controller.onStartup(); controller.onStartup();
@ -89,6 +93,7 @@ public class ListHabitsActivity extends BaseActivity
@Override @Override
protected void onPause() protected void onPause()
{ {
syncManager.stopListening();
midnightTimer.onPause(); midnightTimer.onPause();
screen.onDettached(); screen.onDettached();
adapter.cancelRefresh(); adapter.cancelRefresh();
@ -102,6 +107,7 @@ public class ListHabitsActivity extends BaseActivity
screen.onAttached(); screen.onAttached();
rootView.postInvalidate(); rootView.postInvalidate();
midnightTimer.onResume(); midnightTimer.onResume();
syncManager.startListening();
if (prefs.getTheme() == ThemeSwitcher.THEME_DARK && if (prefs.getTheme() == ThemeSwitcher.THEME_DARK &&
prefs.isPureBlackEnabled() != pureBlack) prefs.isPureBlackEnabled() != pureBlack)

@ -133,6 +133,7 @@ public class ListHabitsScreen extends BaseScreen
public void onCommandExecuted(@NonNull Command command, public void onCommandExecuted(@NonNull Command command,
@Nullable Long refreshKey) @Nullable Long refreshKey)
{ {
if(command.isRemote()) return;
showMessage(command.getExecuteStringId()); showMessage(command.getExecuteStringId());
} }

@ -61,6 +61,13 @@ public class SettingsFragment extends PreferenceFragmentCompat
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
Context appContext = getContext().getApplicationContext();
if(appContext instanceof HabitsApplication)
{
HabitsApplication app = (HabitsApplication) appContext;
prefs = app.getComponent().getPreferences();
}
setResultOnPreferenceClick("importData", RESULT_IMPORT_DATA); setResultOnPreferenceClick("importData", RESULT_IMPORT_DATA);
setResultOnPreferenceClick("exportCSV", RESULT_EXPORT_CSV); setResultOnPreferenceClick("exportCSV", RESULT_EXPORT_CSV);
setResultOnPreferenceClick("exportDB", RESULT_EXPORT_DB); setResultOnPreferenceClick("exportDB", RESULT_EXPORT_DB);
@ -68,13 +75,21 @@ public class SettingsFragment extends PreferenceFragmentCompat
setResultOnPreferenceClick("bugReport", RESULT_BUG_REPORT); setResultOnPreferenceClick("bugReport", RESULT_BUG_REPORT);
updateRingtoneDescription(); updateRingtoneDescription();
updateSync();
}
Context appContext = getContext().getApplicationContext(); private void updateSync()
if(appContext instanceof HabitsApplication)
{ {
HabitsApplication app = (HabitsApplication) appContext; if(prefs == null) return;
prefs = app.getComponent().getPreferences(); boolean enabled = prefs.isSyncFeatureEnabled();
}
Preference syncKey = findPreference("pref_sync_key");
syncKey.setSummary(prefs.getSyncKey());
syncKey.setVisible(enabled);
Preference syncAddress = findPreference("pref_sync_address");
syncAddress.setSummary(prefs.getSyncAddress());
syncAddress.setVisible(enabled);
} }
@Override @Override
@ -127,6 +142,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
String key) String key)
{ {
BackupManager.dataChanged("org.isoron.uhabits"); BackupManager.dataChanged("org.isoron.uhabits");
updateSync();
} }
private void setResultOnPreferenceClick(String key, final int result) private void setResultOnPreferenceClick(String key, final int result)

@ -39,14 +39,18 @@ public abstract class Command
{ {
private String id; private String id;
private boolean isRemote;
public Command() public Command()
{ {
id = DatabaseUtils.getRandomId(); id = DatabaseUtils.getRandomId();
isRemote = false;
} }
public Command(String id) public Command(String id)
{ {
this.id = id; this.id = id;
isRemote = false;
} }
public abstract void execute(); public abstract void execute();
@ -71,6 +75,16 @@ public abstract class Command
return null; return null;
} }
public boolean isRemote()
{
return isRemote;
}
public void setRemote(boolean remote)
{
isRemote = remote;
}
@NonNull @NonNull
public JSONObject toJson() public JSONObject toJson()
{ {

@ -26,12 +26,15 @@ import com.google.gson.*;
import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.*;
import org.json.*; import org.json.*;
import javax.inject.*;
public class CommandParser public class CommandParser
{ {
private HabitList habitList; private HabitList habitList;
private ModelFactory modelFactory; private ModelFactory modelFactory;
@Inject
public CommandParser(@NonNull HabitList habitList, public CommandParser(@NonNull HabitList habitList,
@NonNull ModelFactory modelFactory) @NonNull ModelFactory modelFactory)
{ {

@ -95,9 +95,9 @@ public class CreateRepetitionCommand extends Command
@NonNull @NonNull
public String event = "CreateRep"; public String event = "CreateRep";
public long habitId; public long habit;
public long timestamp; public long repTimestamp;
public int value; public int value;
@ -107,18 +107,18 @@ public class CreateRepetitionCommand extends Command
Long habitId = command.habit.getId(); Long habitId = command.habit.getId();
if(habitId == null) throw new RuntimeException("Habit not saved"); if(habitId == null) throw new RuntimeException("Habit not saved");
this.habitId = habitId; this.habit = habitId;
this.timestamp = command.timestamp; this.repTimestamp = command.timestamp;
this.value = command.value; this.value = command.value;
} }
public CreateRepetitionCommand toCommand(@NonNull HabitList habitList) public CreateRepetitionCommand toCommand(@NonNull HabitList habitList)
{ {
Habit h = habitList.getById(habitId); Habit h = habitList.getById(habit);
if(h == null) throw new HabitNotFoundException(); if(h == null) throw new HabitNotFoundException();
CreateRepetitionCommand command; CreateRepetitionCommand command;
command = new CreateRepetitionCommand(h, timestamp, value); command = new CreateRepetitionCommand(h, repTimestamp, value);
command.setId(id); command.setId(id);
return command; return command;
} }

@ -73,9 +73,9 @@ public class ToggleRepetitionCommand extends Command
@NonNull @NonNull
public String event = "Toggle"; public String event = "Toggle";
public long habitId; public long habit;
public long timestamp; public long repTimestamp;
public Record(@NonNull ToggleRepetitionCommand command) public Record(@NonNull ToggleRepetitionCommand command)
{ {
@ -83,17 +83,17 @@ public class ToggleRepetitionCommand extends Command
Long habitId = command.habit.getId(); Long habitId = command.habit.getId();
if(habitId == null) throw new RuntimeException("Habit not saved"); if(habitId == null) throw new RuntimeException("Habit not saved");
this.timestamp = command.timestamp; this.repTimestamp = command.timestamp;
this.habitId = habitId; this.habit = habitId;
} }
public ToggleRepetitionCommand toCommand(@NonNull HabitList habitList) public ToggleRepetitionCommand toCommand(@NonNull HabitList habitList)
{ {
Habit h = habitList.getById(habitId); Habit h = habitList.getById(habit);
if(h == null) throw new HabitNotFoundException(); if(h == null) throw new HabitNotFoundException();
ToggleRepetitionCommand command; ToggleRepetitionCommand command;
command = new ToggleRepetitionCommand(h, timestamp); command = new ToggleRepetitionCommand(h, repTimestamp);
command.setId(id); command.setId(id);
return command; return command;
} }

@ -28,7 +28,6 @@ import java.util.*;
import javax.inject.*; import javax.inject.*;
import static android.R.attr.*;
import static org.isoron.uhabits.models.Checkmark.*; import static org.isoron.uhabits.models.Checkmark.*;
/** /**
@ -328,7 +327,7 @@ public class Habit
public boolean isNumerical() public boolean isNumerical()
{ {
return type == NUMBER_HABIT; return data.type == NUMBER_HABIT;
} }
public HabitData getData() public HabitData getData()

@ -77,6 +77,26 @@ public class Preferences
} }
} }
public String getSyncAddress()
{
return prefs.getString("pref_sync_address", "https://sync.loophabits.org:4000");
}
public String getSyncClientId()
{
String id = prefs.getString("pref_sync_client_id", "");
if(!id.isEmpty()) return id;
id = UUID.randomUUID().toString();
prefs.edit().putString("pref_sync_client_id", id).apply();
return id;
}
public boolean isSyncFeatureEnabled()
{
return prefs.getBoolean("pref_feature_sync", false);
}
public void setDefaultOrder(HabitList.Order order) public void setDefaultOrder(HabitList.Order order)
{ {
prefs.edit().putString("pref_default_order", order.name()).apply(); prefs.edit().putString("pref_default_order", order.name()).apply();
@ -117,7 +137,7 @@ public class Preferences
public long getLastSync() public long getLastSync()
{ {
return prefs.getLong("lastSync", 0); return prefs.getLong("last_sync", 0);
} }
public void setLastSync(long timestamp) public void setLastSync(long timestamp)

@ -26,7 +26,6 @@ import android.util.*;
import org.isoron.uhabits.*; import org.isoron.uhabits.*;
import org.isoron.uhabits.commands.*; import org.isoron.uhabits.commands.*;
import org.isoron.uhabits.preferences.*; import org.isoron.uhabits.preferences.*;
import org.isoron.uhabits.utils.*;
import org.json.*; import org.json.*;
import java.io.*; import java.io.*;
@ -36,6 +35,7 @@ import java.security.cert.Certificate;
import java.security.cert.*; import java.security.cert.*;
import java.util.*; import java.util.*;
import javax.inject.*;
import javax.net.ssl.*; import javax.net.ssl.*;
import io.socket.client.*; import io.socket.client.*;
@ -44,7 +44,7 @@ import io.socket.emitter.*;
import static io.socket.client.Socket.*; import static io.socket.client.Socket.*;
public class SyncManager public class SyncManager implements CommandRunner.Listener
{ {
public static final String EVENT_AUTH = "auth"; public static final String EVENT_AUTH = "auth";
@ -58,12 +58,9 @@ public class SyncManager
public static final String EVENT_POST_EVENT = "postEvent"; public static final String EVENT_POST_EVENT = "postEvent";
public static final String SYNC_SERVER_URL = private String clientId;
"https://sync.loophabits.org:4000";
private static String CLIENT_ID; private String groupKey;
private static String GROUP_KEY;
@NonNull @NonNull
private Socket socket; private Socket socket;
@ -84,7 +81,8 @@ public class SyncManager
private CommandParser commandParser; private CommandParser commandParser;
public SyncManager(@NonNull Context context, @Inject
public SyncManager(@AppContext @NonNull Context context,
@NonNull Preferences prefs, @NonNull Preferences prefs,
@NonNull CommandRunner commandRunner, @NonNull CommandRunner commandRunner,
@NonNull CommandParser commandParser) @NonNull CommandParser commandParser)
@ -97,15 +95,16 @@ public class SyncManager
pendingConfirmation = new LinkedList<>(); pendingConfirmation = new LinkedList<>();
pendingEmit = Event.getAll(); pendingEmit = Event.getAll();
GROUP_KEY = prefs.getSyncKey(); groupKey = prefs.getSyncKey();
CLIENT_ID = DatabaseUtils.getRandomId(); clientId = prefs.getSyncClientId();
String serverURL = prefs.getSyncAddress();
Log.d("SyncManager", CLIENT_ID); Log.d("SyncManager", clientId);
try try
{ {
IO.setDefaultSSLContext(getCACertSSLContext()); IO.setDefaultSSLContext(getCACertSSLContext());
socket = IO.socket(SYNC_SERVER_URL); socket = IO.socket(serverURL);
logSocketEvent(socket, EVENT_CONNECT, "Connected"); logSocketEvent(socket, EVENT_CONNECT, "Connected");
logSocketEvent(socket, EVENT_CONNECT_TIMEOUT, "Connect timeout"); logSocketEvent(socket, EVENT_CONNECT_TIMEOUT, "Connect timeout");
logSocketEvent(socket, EVENT_CONNECTING, "Connecting..."); logSocketEvent(socket, EVENT_CONNECTING, "Connecting...");
@ -124,8 +123,6 @@ public class SyncManager
socket.on(EVENT_EXECUTE_EVENT, new OnExecuteCommandListener()); socket.on(EVENT_EXECUTE_EVENT, new OnExecuteCommandListener());
socket.on(EVENT_AUTH_OK, new OnAuthOKListener()); socket.on(EVENT_AUTH_OK, new OnAuthOKListener());
socket.on(EVENT_FETCH_OK, new OnFetchOKListener()); socket.on(EVENT_FETCH_OK, new OnFetchOKListener());
socket.connect();
} }
catch (URISyntaxException e) catch (URISyntaxException e)
{ {
@ -133,14 +130,12 @@ public class SyncManager
} }
} }
public void close() @Override
public void onCommandExecuted(@NonNull Command command,
@Nullable Long refreshKey)
{ {
socket.off(); if(command.isRemote()) return;
socket.close();
}
public void postCommand(Command command)
{
JSONObject msg = command.toJson(); JSONObject msg = command.toJson();
Long now = new Date().getTime(); Long now = new Date().getTime();
Event e = new Event(command.getId(), now, msg.toString()); Event e = new Event(command.getId(), now, msg.toString());
@ -152,6 +147,21 @@ public class SyncManager
if (readyToEmit) emitPending(); if (readyToEmit) emitPending();
} }
public void startListening()
{
if(!prefs.isSyncFeatureEnabled()) return;
if(groupKey.isEmpty()) return;
socket.connect();
commandRunner.addListener(this);
}
public void stopListening()
{
commandRunner.removeListener(this);
socket.close();
}
private void emitPending() private void emitPending()
{ {
try try
@ -200,7 +210,13 @@ public class SyncManager
private void logSocketEvent(Socket socket, String event, final String msg) private void logSocketEvent(Socket socket, String event, final String msg)
{ {
socket.on(event, args -> Log.i("SyncManager", msg)); socket.on(event, args ->
{
Log.i("SyncManager", msg);
for (Object o : args)
if (o instanceof SocketIOException)
((SocketIOException) o).printStackTrace();
});
} }
private void updateLastSync(Long timestamp) private void updateLastSync(Long timestamp)
@ -249,8 +265,8 @@ public class SyncManager
try try
{ {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("groupKey", GROUP_KEY); json.put("groupKey", groupKey);
json.put("clientId", CLIENT_ID); json.put("clientId", clientId);
json.put("version", BuildConfig.VERSION_NAME); json.put("version", BuildConfig.VERSION_NAME);
return json; return json;
} }
@ -292,6 +308,8 @@ public class SyncManager
private void executeCommand(JSONObject root) throws JSONException private void executeCommand(JSONObject root) throws JSONException
{ {
Command received = commandParser.parse(root); Command received = commandParser.parse(root);
received.setRemote(true);
for (Event e : pendingConfirmation) for (Event e : pendingConfirmation)
{ {
if (e.serverId.equals(received.getId())) if (e.serverId.equals(received.getId()))

@ -147,10 +147,18 @@
android:key="pref_feature_numerical_habits" android:key="pref_feature_numerical_habits"
android:title="Enable numerical habits"/> android:title="Enable numerical habits"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="pref_feature_sync"
android:title="Enable cloud sync"/>
<EditTextPreference
android:key="pref_sync_address"
android:title="Sync server address"/>
<EditTextPreference <EditTextPreference
android:key="pref_sync_key" android:key="pref_sync_key"
android:title="Sync: group key" android:title="Sync key"/>
android:summary="%s"/>
</PreferenceCategory> </PreferenceCategory>

Loading…
Cancel
Save