Skip to content
This repository has been archived by the owner on Aug 13, 2021. It is now read-only.

Commit

Permalink
Merge pull request #35 from schul-cloud/38-improve-calendar-sync
Browse files Browse the repository at this point in the history
38 improve calendar sync
  • Loading branch information
Langleu authored Jun 22, 2017
2 parents 1e8ca96 + 18c5e7d commit f444aaf
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,28 @@ public String saveCurrentStorageContext(String path) {
return null;
}

public Boolean saveCalendarSyncEnabled(Boolean isEnabled) {
SharedPreferences.Editor editor = mPref.edit();

editor.putBoolean("calendarSyncEnabled", isEnabled);
if (editor.commit()) {
return isEnabled;
}

return null;
}

public String saveCalendarSyncName(String calendarName) {
SharedPreferences.Editor editor = mPref.edit();

editor.putString("calendarSyncName", calendarName);
if (editor.commit()) {
return calendarName;
}

return null;
}

// ##### Getter

public String getAccessToken() {
Expand All @@ -113,6 +135,13 @@ public String getCurrentStorageContext() {
return mPref.getString("storageContext", "null");
}

public Boolean getCalendarSyncEnabled() {
return mPref.getBoolean("calendarSyncEnabled", false);
}

public String getCalendarSyncName() {
return mPref.getString("calendarSyncName", "null");
}

// ##### Clearing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SwitchCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.beardedhen.androidbootstrap.BootstrapButton;
import com.github.johnpersano.supertoasts.library.utils.PaletteUtils;

import org.schulcloud.mobile.R;
import org.schulcloud.mobile.data.local.PreferencesHelper;
import org.schulcloud.mobile.data.model.Device;
import org.schulcloud.mobile.data.model.Event;
import org.schulcloud.mobile.data.sync.DeviceSyncService;
Expand Down Expand Up @@ -41,18 +45,24 @@ public class SettingsActivity extends BaseActivity implements SettingsMvpView {
@Inject
SettingsPresenter mSettingsPresenter;

@Inject
PreferencesHelper mPreferencesHelper;

@Inject
DevicesAdapter mDevicesAdapter;

@BindView(R.id.btn_add_calendar)
BootstrapButton btn_add_calendar;
@BindView(R.id.switch_calendar)
SwitchCompat switch_calendar;

@BindView(R.id.btn_create_device)
BootstrapButton btn_create_device;

@BindView(R.id.devices_recycler_view)
RecyclerView devices_recycler_view;

@BindView(R.id.name_local_calendar)
TextView name_local_calendar;

/**
* Return an Intent to start this Activity.
* triggerDataSyncOnCreate allows disabling the background sync service onCreate. Should
Expand Down Expand Up @@ -82,6 +92,7 @@ protected void onCreate(Bundle savedInstanceState) {
mSettingsPresenter.attachView(this);
mSettingsPresenter.checkSignedIn(this);

if (mPreferencesHelper.getCalendarSyncEnabled()) mSettingsPresenter.loadEvents(false);
mSettingsPresenter.loadDevices();

if (getIntent().getBooleanExtra(EXTRA_TRIGGER_SYNC_FLAG, true)) {
Expand All @@ -90,7 +101,22 @@ protected void onCreate(Bundle savedInstanceState) {
}

btn_create_device.setOnClickListener(view -> mSettingsPresenter.registerDevice());
btn_add_calendar.setOnClickListener(view -> mSettingsPresenter.loadEvents());

initializeCalendarSwitch(
mPreferencesHelper.getCalendarSyncEnabled(),
mPreferencesHelper.getCalendarSyncName());

switch_calendar.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) mSettingsPresenter.loadEvents(true);
mPreferencesHelper.saveCalendarSyncEnabled(isChecked);
initializeCalendarSwitch(isChecked, mPreferencesHelper.getCalendarSyncName());
});
}

private void initializeCalendarSwitch(Boolean isChecked, String calendarName) {
switch_calendar.setChecked(isChecked);
name_local_calendar.setVisibility(isChecked ? View.VISIBLE : View.INVISIBLE);
name_local_calendar.setText(calendarName.equals("null") ? "" : calendarName);
}

@Override
Expand All @@ -110,7 +136,7 @@ public void goToSignIn() {

@Override
public void showEventsEmpty() {
Toast.makeText(this, R.string.empty_events, Toast.LENGTH_LONG).show();
//Toast.makeText(this, R.string.empty_events, Toast.LENGTH_LONG).show();
}

@Override
Expand All @@ -127,7 +153,7 @@ public void reload() {
}

@Override
public void connectToCalendar(List<Event> events) {
public void connectToCalendar(List<Event> events, Boolean promptForCalendar) {
// grant calendar permission, powered sdk version 23
PermissionsUtil.checkPermissions(
CALENDAR_PERMISSION_CALLBACK_ID,
Expand All @@ -142,24 +168,44 @@ public void connectToCalendar(List<Event> events) {
// saves selected calendar index on dialog prompting
final Integer[] chosenValueIndex = new Integer[1];

DialogFactory.createSingleSelectDialog(
this,
calendarValues,
R.string.choose_calendar)
.setItems(calendarValues, (dialogInterface, i) -> chosenValueIndex[0] = i) // update choice
.setPositiveButton(R.string.dialog_action_ok, (dialogInterface, i) -> { // handle choice
if (chosenValueIndex[0] != null && chosenValueIndex[0] > 0) {
Log.i("[CALENDAR CHOSEN]: ", calendarValues[chosenValueIndex[0]].toString());

// send all events to calendar
mSettingsPresenter.writeEventsToLocalCalendar(chosenValueIndex[0], events, calendarContentUtil);
}
})
.show();
if (promptForCalendar) {
DialogFactory.createSingleSelectDialog(
this,
calendarValues,
R.string.choose_calendar)
.setItems(calendarValues, (dialogInterface, i) -> chosenValueIndex[0] = i) // update choice
.setPositiveButton(R.string.dialog_action_ok, (dialogInterface, i) -> { // handle choice
if (chosenValueIndex[0] != null && chosenValueIndex[0] > 0) {

String calendarName = calendarValues[chosenValueIndex[0]].toString();
Log.i("[CALENDAR CHOSEN]: ", calendarName);
mPreferencesHelper.saveCalendarSyncName(calendarName);

// send all events to calendar
mSettingsPresenter.writeEventsToLocalCalendar(
calendarName,
events,
calendarContentUtil,
promptForCalendar);
}
})
.show();
} else {
mSettingsPresenter.writeEventsToLocalCalendar(
mPreferencesHelper.getCalendarSyncName(),
events,
calendarContentUtil,
promptForCalendar);
}

}

@Override
public void showSyncToCalendarSuccessful() {
Toast.makeText(this, R.string.sync_calendar_successful, Toast.LENGTH_LONG).show();
DialogFactory.createSuperToast(
this,
getResources().getString(R.string.sync_calendar_successful),
PaletteUtils.getSolidColor(PaletteUtils.MATERIAL_GREEN))
.show();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public interface SettingsMvpView extends MvpView {

void reload();

void connectToCalendar(List<Event> events);
void connectToCalendar(List<Event> events, Boolean promptForCalendar);

void showSyncToCalendarSuccessful();
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@

import retrofit2.Response;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import timber.log.Timber;

@ConfigPersistent
public class SettingsPresenter extends BasePresenter<SettingsMvpView> {

private Subscription eventSubscription;

@Inject
public SettingsPresenter(DataManager dataManager) {
mDataManager = dataManager;
Expand All @@ -45,15 +48,17 @@ public void attachView(SettingsMvpView mvpView) {
public void detachView() {
super.detachView();
if (mSubscription != null) mSubscription.unsubscribe();
if (eventSubscription != null) eventSubscription.unsubscribe();
}

/**
* fetching events from local db
* @param promptForCalendar {Boolean} - whether to open a calendar-choose-dialog
*/
public void loadEvents() {
public void loadEvents(Boolean promptForCalendar) {
checkViewAttached();
RxUtil.unsubscribe(mSubscription);
mSubscription = mDataManager.getEvents()
RxUtil.unsubscribe(eventSubscription);
eventSubscription = mDataManager.getEvents()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<Event>>() {
@Override
Expand All @@ -70,7 +75,7 @@ public void onNext(List<Event> events) {
if (events.isEmpty()) {
getMvpView().showEventsEmpty();
} else {
getMvpView().connectToCalendar(events);
getMvpView().connectToCalendar(events, promptForCalendar);
}
}
});
Expand All @@ -79,11 +84,12 @@ public void onNext(List<Event> events) {
/**
* Syncs given Events to local calendar
*
* @param calendarId {Integer} - the calendar in which the events will be inserted
* @param calendarName {String} - the calendar in which the events will be inserted
* @param events {List<Event>} - the events which will be inserted into the calendar
* @param calendarContentUtil {CalendarContentUtil} - an instance of the CalendarContentUtil for handling the local calendar storage
* @param showToast {Boolean} - whether to show a toast after writing
*/
public void writeEventsToLocalCalendar(Integer calendarId, List<Event> events, CalendarContentUtil calendarContentUtil) {
public void writeEventsToLocalCalendar(String calendarName, List<Event> events, CalendarContentUtil calendarContentUtil, Boolean showToast) {
for (Event event : events) {
// syncing by deleting first and writing again
calendarContentUtil.deleteEventByUid(event._id);
Expand Down Expand Up @@ -128,10 +134,10 @@ public void writeEventsToLocalCalendar(Integer calendarId, List<Event> events, C
// do nothing when its not a recurrent event
}

calendarContentUtil.createEvent(calendarId, event, recurringRule);
calendarContentUtil.createEvent(calendarName, event, recurringRule);
}

getMvpView().showSyncToCalendarSuccessful();
if (showToast) getMvpView().showSyncToCalendarSuccessful();
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

public class CalendarContentUtil {
public static final String[] FIELDS = {
CalendarContract.Calendars._ID,
CalendarContract.Calendars.NAME,
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,
CalendarContract.Calendars.CALENDAR_COLOR,
Expand Down Expand Up @@ -66,18 +67,18 @@ public Set<String> getCalendars() {
}

/**
* @param calendarId {Integer} - the id of the calendar in which the event will be inserted
* @param event {Event} - a new event
* @param recurringRule {String} - a rule for recurring events, e.g. "FREQ=DAILY;COUNT=20;BYDAY=MO,TU,WE,TH,FR;WKST=MO"
* @return {long} - the created event it
*/
public long createEvent(Integer calendarId, Event event, String recurringRule) {
public long createEvent(String calendarName, Event event, String recurringRule) {

ContentValues values = new ContentValues();
values.put(Events.DTSTART, event.start);
values.put(Events.DTEND, event.end);
values.put(Events.TITLE, event.title);
values.put(Events.DESCRIPTION, event.summary);
values.put(Events.CALENDAR_ID, calendarId);
values.put(Events.CALENDAR_ID, getCalendarIdForName(calendarName));
values.put(Events.EVENT_TIMEZONE, "Germany/Berlin");
values.put(Events.UID_2445, event._id);

Expand All @@ -97,6 +98,23 @@ public long createEvent(Integer calendarId, Event event, String recurringRule) {
return Long.parseLong(uri.getLastPathSegment());
}

public String getCalendarIdForName(String calendarName) {
String selection = "(" + CalendarContract.Calendars.NAME + " = ?)";
String[] selectionArgs = new String[] {calendarName};
Cursor cursor = contentResolver.query(CALENDAR_URI, FIELDS, selection, selectionArgs, null);

try {
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String id = cursor.getString(0);
return id;
}
}
} catch (AssertionError ex) { /*TODO: log exception and bail*/ }

return "";
}

/**
* deletes a event in the local android event db for a given uid (the _id property of the event-model)
*
Expand Down
32 changes: 21 additions & 11 deletions app/src/main/res/layouts/settings/layout/activity_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">

<!-- Calendar -->
<RelativeLayout
android:id="@+id/section_calendar"
android:layout_width="match_parent"
Expand All @@ -30,26 +31,36 @@
android:textColor="@color/hpiRed"
android:textSize="@dimen/text_title"/>

<com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/btn_add_calendar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<android.support.v7.widget.SwitchCompat
android:layout_below="@+id/settings_calendar"
android:layout_centerHorizontal="true"
android:id="@+id/switch_calendar"
android:textColorLink="@color/hpiRed"
android:text="@string/add_to_calendar"
app:bootstrapSize="lg"
app:buttonMode="regular"
app:roundedCorners="true"
app:showOutline="false"/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

<TextView
android:id="@+id/name_local_calendar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="@dimen/bootstrap_alert_paddings"
android:text="Calendar-Name"
android:layout_alignBaseline="@+id/switch_calendar"
android:layout_alignBottom="@+id/switch_calendar"
android:layout_toRightOf="@+id/switch_calendar"
android:layout_toEndOf="@+id/switch_calendar"/>

</RelativeLayout>

<!-- Notifications -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/section_calendar"
android:paddingLeft="@dimen/bootstrap_alert_paddings"
android:paddingRight="@dimen/bootstrap_alert_paddings"
android:paddingTop="@dimen/bootstrap_alert_paddings">
android:paddingTop="@dimen/bootstrap_alert_paddings"
android:id="@+id/relativeLayout">

<TextView
android:id="@+id/settings_notifications"
Expand Down Expand Up @@ -89,6 +100,5 @@
android:scrollbars="vertical"/>

</RelativeLayout>

</RelativeLayout>
</ScrollView>
Loading

0 comments on commit f444aaf

Please sign in to comment.