Initiate DAV service refresh after migration

* initiate DAV service refresh after migration
* minor refactoring of sync adapter classes
* minor UI changes
pull/2/head
Ricki Hirner 8 years ago
parent 51867c5f3f
commit 28e7c91658

@ -16,9 +16,11 @@ import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.PeriodicSync;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CalendarContract;
@ -86,9 +88,11 @@ public class AccountSettings {
if (version < CURRENT_VERSION) {
Notification notify = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setSmallIcon(R.drawable.ic_new_releases_light)
.setLargeIcon(((BitmapDrawable)context.getResources().getDrawable(R.drawable.ic_launcher)).getBitmap())
.setContentTitle(context.getString(R.string.settings_version_update))
.setContentText(context.getString(R.string.settings_version_update_warning))
.setContentText(context.getString(R.string.settings_version_update_settings_updated))
.setSubText(context.getString(R.string.settings_version_update_install_hint))
.setCategory(NotificationCompat.CATEGORY_SYSTEM)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setLocalOnly(true)
@ -258,6 +262,8 @@ public class AccountSettings {
// Don't show a warning for Android updates anymore
accountManager.setUserData(account, "last_android_version", null);
Long serviceCardDAV = null, serviceCalDAV = null;
ServiceDB.OpenHelper dbHelper = new ServiceDB.OpenHelper(context);
try {
SQLiteDatabase db = dbHelper.getWritableDatabase();
@ -276,11 +282,11 @@ public class AccountSettings {
ContentValues values = new ContentValues();
values.put(Services.ACCOUNT_NAME, account.name);
values.put(Services.SERVICE, Services.SERVICE_CARDDAV);
long service = db.insert(Services._TABLE, null, values);
serviceCardDAV = db.insert(Services._TABLE, null, values);
// insert address book
values.clear();
values.put(Collections.SERVICE_ID, service);
values.put(Collections.SERVICE_ID, serviceCardDAV);
values.put(Collections.URL, url);
values.put(Collections.SYNC, 1);
db.insert(Collections._TABLE, null, values);
@ -288,10 +294,11 @@ public class AccountSettings {
// insert home set
HttpUrl homeSet = HttpUrl.parse(url).resolve("../");
values.clear();
values.put(HomeSets.SERVICE_ID, service);
values.put(HomeSets.SERVICE_ID, serviceCardDAV);
values.put(HomeSets.URL, homeSet.toString());
db.insert(HomeSets._TABLE, null, values);
}
} catch (ContactsStorageException e) {
App.log.log(Level.SEVERE, "Couldn't migrate address book", e);
} finally {
@ -339,12 +346,12 @@ public class AccountSettings {
ContentValues values = new ContentValues();
values.put(Services.ACCOUNT_NAME, account.name);
values.put(Services.SERVICE, Services.SERVICE_CALDAV);
long service = db.insert(Services._TABLE, null, values);
serviceCalDAV = db.insert(Services._TABLE, null, values);
// insert collections
for (String url : collections) {
values.clear();
values.put(Collections.SERVICE_ID, service);
values.put(Collections.SERVICE_ID, serviceCalDAV);
values.put(Collections.URL, url);
values.put(Collections.SYNC, 1);
db.insert(Collections._TABLE, null, values);
@ -353,16 +360,27 @@ public class AccountSettings {
// insert home sets
for (HttpUrl homeSet : homeSets) {
values.clear();
values.put(HomeSets.SERVICE_ID, service);
values.put(HomeSets.SERVICE_ID, serviceCalDAV);
values.put(HomeSets.URL, homeSet.toString());
db.insert(HomeSets._TABLE, null, values);
}
}
} finally {
dbHelper.close();
}
// initiate service detection (refresh) to get display names, colors etc.
Intent refresh = new Intent(context, DavService.class);
refresh.setAction(DavService.ACTION_REFRESH_COLLECTIONS);
if (serviceCardDAV != null) {
refresh.putExtra(DavService.EXTRA_DAV_SERVICE_ID, serviceCardDAV);
context.startService(refresh);
}
if (serviceCalDAV != null) {
refresh.putExtra(DavService.EXTRA_DAV_SERVICE_ID, serviceCalDAV);
context.startService(refresh);
}
accountManager.setUserData(account, KEY_SETTINGS_VERSION, "3");
}

@ -123,6 +123,7 @@ public class App extends Application implements SharedPreferences.OnSharedPrefer
if (dir != null)
try {
String pattern = new File(dir, "davdroid%u-" + DateFormatUtils.format(System.currentTimeMillis(), "yyyyMMdd-HHmmss") + ".txt").toString();
log.info("Logging to " + pattern);
FileHandler fileHandler = new FileHandler(pattern);
fileHandler.setFormatter(PlainTextFormatter.DEFAULT);

@ -45,7 +45,7 @@ import lombok.Cleanup;
public class LocalCalendar extends AndroidCalendar implements LocalCollection {
public static final int defaultColor = 0xFFC3EA6E; // "DAVdroid green"
public static final int defaultColor = 0xFF8bc34a; // light green 500
public static final String COLUMN_CTAG = Calendars.CAL_SYNC1;

@ -79,23 +79,8 @@ public class CalendarSyncManager extends SyncManager {
}
@Override
protected void queryCapabilities() throws DavException, IOException, HttpException, CalendarStorageException {
davCollection.propfind(0, DisplayName.NAME, CalendarColor.NAME, GetCTag.NAME);
// update name and color
App.log.info("Setting calendar name and color (if available)");
ContentValues values = new ContentValues(2);
DisplayName pDisplayName = (DisplayName)davCollection.properties.get(DisplayName.NAME);
if (pDisplayName != null && !TextUtils.isEmpty(pDisplayName.displayName))
values.put(Calendars.CALENDAR_DISPLAY_NAME, pDisplayName.displayName);
CalendarColor pColor = (CalendarColor)davCollection.properties.get(CalendarColor.NAME);
if (pColor != null && pColor.color != null)
values.put(Calendars.CALENDAR_COLOR, pColor.color);
if (values.size() > 0)
localCalendar().update(values);
protected void queryCapabilities() throws DavException, IOException, HttpException {
davCollection.propfind(0, GetCTag.NAME);
}
@Override

@ -35,41 +35,24 @@ import at.bitfire.davdroid.resource.LocalCalendar;
import at.bitfire.ical4android.CalendarStorageException;
import lombok.Cleanup;
public class CalendarsSyncAdapterService extends Service {
private static SyncAdapter syncAdapter;
private OpenHelper dbHelper;
public class CalendarsSyncAdapterService extends SyncAdapterService {
@Override
public void onCreate() {
dbHelper = new OpenHelper(this);
syncAdapter = new SyncAdapter(this, dbHelper.getReadableDatabase());
super.onCreate();
syncAdapter = new SyncAdapter(this, dbHelper);
}
@Override
public void onDestroy() {
dbHelper.close();
}
@Override
public IBinder onBind(Intent intent) {
return syncAdapter.getSyncAdapterBinder();
}
private static class SyncAdapter extends SyncAdapterService.SyncAdapter {
private static class SyncAdapter extends AbstractThreadedSyncAdapter {
private final SQLiteDatabase db;
public SyncAdapter(Context context, SQLiteDatabase db) {
super(context, false);
this.db = db;
public SyncAdapter(Context context, OpenHelper dbHelper) {
super(context, dbHelper);
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
App.log.info("Starting calendar sync (" + authority + ")");
// required for ical4j and dav4android (ServiceLoader)
Thread.currentThread().setContextClassLoader(getContext().getClassLoader());
super.onPerformSync(account, extras, authority, provider, syncResult);
try {
updateLocalCalendars(provider, account);

@ -25,6 +25,7 @@ import android.support.annotation.Nullable;
import java.util.List;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.model.CollectionInfo;
import at.bitfire.davdroid.model.ServiceDB;
@ -32,41 +33,24 @@ import at.bitfire.davdroid.model.ServiceDB.Collections;
import at.bitfire.davdroid.model.ServiceDB.OpenHelper;
import lombok.Cleanup;
public class ContactsSyncAdapterService extends Service {
private static ContactsSyncAdapter syncAdapter;
private OpenHelper dbHelper;
public class ContactsSyncAdapterService extends SyncAdapterService {
@Override
public void onCreate() {
dbHelper = new OpenHelper(this);
syncAdapter = new ContactsSyncAdapter(this, dbHelper.getReadableDatabase());
super.onCreate();
syncAdapter = new ContactsSyncAdapter(this, dbHelper);
}
@Override
public void onDestroy() {
dbHelper.close();
}
@Override
public IBinder onBind(Intent intent) {
return syncAdapter.getSyncAdapterBinder();
}
private static class ContactsSyncAdapter extends AbstractThreadedSyncAdapter {
private final SQLiteDatabase db;
private static class ContactsSyncAdapter extends SyncAdapter {
public ContactsSyncAdapter(Context context, @NonNull SQLiteDatabase db) {
super(context, false);
this.db = db;
public ContactsSyncAdapter(Context context, OpenHelper dbHelper) {
super(context, dbHelper);
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
App.log.info("Starting address book sync (" + authority + ")");
// required for dav4android (ServiceLoader)
Thread.currentThread().setContextClassLoader(getContext().getClassLoader());
super.onPerformSync(account, extras, authority, provider, syncResult);
Long service = getService(account);
if (service != null) {

@ -0,0 +1,69 @@
/*
* Copyright © 2013 2016 Ricki Hirner (bitfire web engineering).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package at.bitfire.davdroid.syncadapter;
import android.accounts.Account;
import android.app.Service;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Nullable;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.model.ServiceDB;
public abstract class SyncAdapterService extends Service {
ServiceDB.OpenHelper dbHelper;
AbstractThreadedSyncAdapter syncAdapter;
@Override
public void onCreate() {
dbHelper = new ServiceDB.OpenHelper(this);
}
@Override
public void onDestroy() {
dbHelper.close();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return syncAdapter.getSyncAdapterBinder();
}
public static abstract class SyncAdapter extends AbstractThreadedSyncAdapter {
protected final SQLiteDatabase db;
public SyncAdapter(Context context, ServiceDB.OpenHelper dbHelper) {
super(context, false);
db = dbHelper.getReadableDatabase();
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
App.log.info("Starting " + authority + " sync");
// required for dav4android (ServiceLoader)
Thread.currentThread().setContextClassLoader(getContext().getClassLoader());
// peek into AccountSettings to cause possible migration (v0.9 -> v1.0)
new AccountSettings(getContext(), account);
}
}
}

@ -46,6 +46,7 @@ import at.bitfire.davdroid.R;
import at.bitfire.davdroid.resource.LocalCollection;
import at.bitfire.davdroid.resource.LocalResource;
import at.bitfire.davdroid.ui.AccountActivity;
import at.bitfire.davdroid.ui.AccountSettingsActivity;
import at.bitfire.davdroid.ui.DebugInfoActivity;
import at.bitfire.ical4android.CalendarStorageException;
import at.bitfire.vcard4android.ContactsStorageException;
@ -112,7 +113,7 @@ abstract public class SyncManager {
httpClient = HttpClient.create(context, account);
// dismiss previous error notifications
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(account.name, this.notificationId = notificationId);
}
@ -209,8 +210,8 @@ abstract public class SyncManager {
final Intent detailsIntent;
if (e instanceof UnauthorizedException) {
detailsIntent = new Intent(context, AccountActivity.class);
detailsIntent.putExtra(AccountActivity.EXTRA_ACCOUNT, account);
detailsIntent = new Intent(context, AccountSettingsActivity.class);
detailsIntent.putExtra(AccountSettingsActivity.EXTRA_ACCOUNT, account);
} else {
detailsIntent = new Intent(context, DebugInfoActivity.class);
detailsIntent.putExtra(DebugInfoActivity.KEY_EXCEPTION, e);

@ -35,41 +35,24 @@ import at.bitfire.ical4android.CalendarStorageException;
import at.bitfire.ical4android.TaskProvider;
import lombok.Cleanup;
public class TasksSyncAdapterService extends Service {
private static SyncAdapter syncAdapter;
private OpenHelper dbHelper;
public class TasksSyncAdapterService extends SyncAdapterService {
@Override
public void onCreate() {
dbHelper = new OpenHelper(this);
syncAdapter = new SyncAdapter(this, dbHelper.getReadableDatabase());
super.onCreate();
syncAdapter = new SyncAdapter(this, dbHelper);
}
@Override
public void onDestroy() {
dbHelper.close();
}
@Override
public IBinder onBind(Intent intent) {
return syncAdapter.getSyncAdapterBinder();
}
private static class SyncAdapter extends AbstractThreadedSyncAdapter {
private final SQLiteDatabase db;
private static class SyncAdapter extends SyncAdapterService.SyncAdapter {
public SyncAdapter(Context context, SQLiteDatabase db) {
super(context, false);
this.db = db;
public SyncAdapter(Context context, OpenHelper dbHelper) {
super(context, dbHelper);
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient providerClient, SyncResult syncResult) {
App.log.info("Starting task sync (" + authority + ")");
// required for ical4j and dav4android (ServiceLoader)
Thread.currentThread().setContextClassLoader(getContext().getClassLoader());
super.onPerformSync(account, extras, authority, providerClient, syncResult);
try {
@Cleanup TaskProvider provider = TaskProvider.acquire(getContext().getContentResolver(), TaskProvider.ProviderName.OpenTasks);

@ -83,23 +83,8 @@ public class TasksSyncManager extends SyncManager {
}
@Override
protected void queryCapabilities() throws DavException, IOException, HttpException, CalendarStorageException {
davCollection.propfind(0, DisplayName.NAME, CalendarColor.NAME, GetCTag.NAME);
// update name and color
App.log.info("Setting task list name and color (if available)");
ContentValues values = new ContentValues(2);
DisplayName pDisplayName = (DisplayName)davCollection.properties.get(DisplayName.NAME);
if (pDisplayName != null && !TextUtils.isEmpty(pDisplayName.displayName))
values.put(TaskLists.LIST_NAME, pDisplayName.displayName);
CalendarColor pColor = (CalendarColor)davCollection.properties.get(CalendarColor.NAME);
if (pColor != null && pColor.color != null)
values.put(TaskLists.LIST_COLOR, pColor.color);
if (values.size() > 0)
localTaskList().update(values);
protected void queryCapabilities() throws DavException, IOException, HttpException {
davCollection.propfind(0, GetCTag.NAME);
}
@Override

@ -413,7 +413,7 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
private List<CollectionInfo> readCollections(@NonNull SQLiteDatabase db, long service) {
List<CollectionInfo> collections = new LinkedList<>();
@Cleanup Cursor cursor = db.query(Collections._TABLE, Collections._COLUMNS, Collections.SERVICE_ID + "=?",
new String[]{ String.valueOf(service )}, null, null, Collections.SUPPORTS_VEVENT + " DESC," + Collections.DISPLAY_NAME);
new String[]{ String.valueOf(service) }, null, null, Collections.SUPPORTS_VEVENT + " DESC," + Collections.DISPLAY_NAME);
while (cursor.moveToNext()) {
ContentValues values = new ContentValues();
DatabaseUtils.cursorRowToContentValues(cursor, values);

@ -13,8 +13,6 @@ import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
@ -29,18 +27,11 @@ import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.LinkedList;
import java.util.List;
import at.bitfire.davdroid.AccountsChangedReceiver;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.model.ServiceDB.OpenHelper;
import at.bitfire.davdroid.model.ServiceDB.Services;
import lombok.Cleanup;
import lombok.RequiredArgsConstructor;
public class AccountListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<List<AccountListFragment.AccountInfo>>, AdapterView.OnItemClickListener {
public class AccountListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Account[]>, AdapterView.OnItemClickListener {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -61,47 +52,39 @@ public class AccountListFragment extends ListFragment implements LoaderManager.L
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
AccountInfo info = (AccountInfo)getListAdapter().getItem(position);
Account account = (Account)getListAdapter().getItem(position);
Intent intent = new Intent(getContext(), AccountActivity.class);
intent.putExtra(AccountActivity.EXTRA_ACCOUNT, info.account);
intent.putExtra(AccountActivity.EXTRA_ACCOUNT, account);
startActivity(intent);
}
// loader
@RequiredArgsConstructor
protected static class AccountInfo {
final Account account;
Long cardDavService, calDavService;
}
@Override
public Loader<List<AccountInfo>> onCreateLoader(int id, Bundle args) {
public Loader<Account[]> onCreateLoader(int id, Bundle args) {
return new AccountLoader(getContext());
}
@Override
public void onLoadFinished(Loader<List<AccountInfo>> loader, List<AccountInfo> accounts) {
public void onLoadFinished(Loader<Account[]> loader, Account[] accounts) {
AccountListAdapter adapter = (AccountListAdapter)getListAdapter();
adapter.clear();
adapter.addAll(accounts);
}
@Override
public void onLoaderReset(Loader<List<AccountInfo>> loader) {
public void onLoaderReset(Loader<Account[]> loader) {
((AccountListAdapter)getListAdapter()).clear();
}
private static class AccountLoader extends AsyncTaskLoader<List<AccountInfo>> implements OnAccountsUpdateListener {
private static class AccountLoader extends AsyncTaskLoader<Account[]> implements OnAccountsUpdateListener {
private final AccountManager accountManager;
private final OpenHelper dbHelper;
public AccountLoader(Context context) {
super(context);
accountManager = AccountManager.get(context);
dbHelper = new OpenHelper(context);
}
@Override
@ -120,43 +103,15 @@ public class AccountListFragment extends ListFragment implements LoaderManager.L
}
@Override
public List<AccountInfo> loadInBackground() {
List<AccountInfo> accounts = new LinkedList<>();
try {
SQLiteDatabase db = dbHelper.getReadableDatabase();
for (Account account : accountManager.getAccountsByType(Constants.ACCOUNT_TYPE)) {
AccountInfo info = new AccountInfo(account);
// query services of this account
@Cleanup Cursor cursor = db.query(
Services._TABLE,
new String[] { Services.ID, Services.SERVICE },
Services.ACCOUNT_NAME + "=?", new String[] { account.name },
null, null, null);
while (cursor.moveToNext()) {
long id = cursor.getLong(0);
String service = cursor.getString(1);
if (Services.SERVICE_CARDDAV.equals(service))
info.cardDavService = id;
if (Services.SERVICE_CALDAV.equals(service))
info.calDavService = id;
}
accounts.add(info);
}
} finally {
dbHelper.close();
}
return accounts;
public Account[] loadInBackground() {
return accountManager.getAccountsByType(Constants.ACCOUNT_TYPE);
}
}
// list adapter
static class AccountListAdapter extends ArrayAdapter<AccountInfo> {
static class AccountListAdapter extends ArrayAdapter<Account> {
public AccountListAdapter(Context context) {
super(context, R.layout.account_list_item);
}
@ -166,16 +121,11 @@ public class AccountListFragment extends ListFragment implements LoaderManager.L
if (v == null)
v = LayoutInflater.from(getContext()).inflate(R.layout.account_list_item, parent, false);
AccountInfo info = getItem(position);
Account account = getItem(position);
TextView tv = (TextView)v.findViewById(R.id.account_name);
tv.setText(info.account.name);
tv = (TextView)v.findViewById(R.id.carddav);
tv.setVisibility(info.cardDavService != null ? View.VISIBLE : View.GONE);
tv.setText(account.name);
tv = (TextView)v.findViewById(R.id.caldav);
tv.setVisibility(info.calDavService != null ? View.VISIBLE : View.GONE);
return v;
}
}

@ -173,13 +173,13 @@ public class AccountSettingsActivity extends AppCompatActivity {
prefSyncTasks.setSummary(R.string.settings_sync_summary_not_available);
}
final Preference prefTimeRangePastDays = findPreference("caldav_time_range_past_days");
final EditTextPreference prefTimeRangePastDays = (EditTextPreference)findPreference("caldav_time_range_past_days");
Integer pastDays = settings.getTimeRangePastDays();
if (pastDays != null) {
//prefTimeRangePastDays.setText(pastDays.toString());
prefTimeRangePastDays.setText(pastDays.toString());
prefTimeRangePastDays.setSummary(getResources().getQuantityString(R.plurals.settings_sync_time_range_past_days, pastDays, pastDays));
} else {
//prefTimeRangePastDays.setText(null);
prefTimeRangePastDays.setText(null);
prefTimeRangePastDays.setSummary(R.string.settings_sync_time_range_past_none);
}
prefTimeRangePastDays.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {

@ -73,10 +73,17 @@ public class AccountsActivity extends AppCompatActivity implements NavigationVie
public boolean onNavigationItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_about:
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("source/").build()));
break;
case R.id.nav_website:
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri));
break;
case R.id.nav_faq:
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("faq/").build()));
break;
case R.id.nav_forums:
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("forums/").build()));
break;
case R.id.nav_donate:
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("donate/").build()));
break;

@ -97,10 +97,10 @@ public class StartupDialogFragment extends DialogFragment {
public void onClick(DialogInterface dialog, int which) {
}
})
.setNeutralButton(R.string.startup_development_version_show_forums, new DialogInterface.OnClickListener() {
.setNeutralButton(R.string.startup_development_version_give_feedback, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("forums/").build()));
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("forums/beta/").build()));
}
})
.create();

@ -0,0 +1,17 @@
<!--
~ Copyright © 2013 2016 Ricki Hirner (bitfire web engineering).
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm0,3c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zm0,14.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</vector>

@ -0,0 +1,18 @@
<!--
~ Copyright © 2013 2016 Ricki Hirner (bitfire web engineering).
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:alpha="0.54" >
<path
android:fillColor="#FF000000"
android:pathData="M21,6h-2v9H6v2c0,0.55 0.45,1 1,1h11l4,4V7c0,-0.55 -0.45,-1 -1,-1zm-4,6V3c0,-0.55 -0.45,-1 -1,-1H3c-0.55,0 -1,0.45 -1,1v14l4,-4h10c0.55,0 1,-0.45 1,-1z"/>
</vector>

@ -10,8 +10,9 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportHeight="24.0"
android:alpha="0.54" >
<path
android:fillColor="#FFFFFFFF"
android:fillColor="#FF000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm1,17h-2v-2h2v2zm2.07,-7.75l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2H8c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"/>
</vector>

@ -0,0 +1,17 @@
<!--
~ Copyright © 2013 2016 Ricki Hirner (bitfire web engineering).
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M23,12l-2.44,-2.78 0.34,-3.68 -3.61,-0.82 -1.89,-3.18L12,3 8.6,1.54 6.71,4.72l-3.61,0.81 0.34,3.68L1,12l2.44,2.78 -0.34,3.69 3.61,0.82 1.89,3.18L12,21l3.4,1.46 1.89,-3.18 3.61,-0.82 -0.34,-3.68L23,12zm-10,5h-2v-2h2v2zm0,-4h-2V7h2v6z"/>
</vector>

@ -10,8 +10,7 @@
android:shape="rectangle">
<gradient
android:angle="135"
android:centerColor="#4CAF50"
android:endColor="#2E7D32"
android:startColor="#81C784"
android:endColor="@color/light_green300"
android:startColor="@color/green700"
android:type="linear"/>
</shape>

@ -14,54 +14,27 @@
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground"
card_view:contentPadding="16dp"
card_view:cardBackgroundColor="#ececec"
card_view:cardBackgroundColor="@color/orange400"
card_view:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right|center_vertical">
<ProgressBar
android:id="@+id/synchronizing"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="invisible"
style="@android:style/Widget.ProgressBar.Small"/>
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="@+id/carddav"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/chip"
android:text="CardDAV"/>
<TextView
android:id="@+id/caldav"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
style="@style/chip"
android:text="CalDAV"/>
</LinearLayout>
<TextView
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@drawable/ic_account_circle_white"/>
<TextView
android:id="@+id/account_name"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/carddav"
android:layout_marginTop="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textColor="@color/white"
tools:text="Account Name"/>
</LinearLayout>

@ -16,27 +16,28 @@
android:fitsSystemWindows="true"
tools:context="at.bitfire.davdroid.ui.AccountsActivity">
<fragment
class="at.bitfire.davdroid.ui.AccountListFragment"
android:id="@+id/account_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/account_list"
app:layout_scrollFlags="scroll"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
app:theme="@style/ThemeOverlay.AppCompat.ActionBar"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
/>
android:background="?attr/colorPrimary"/>
</android.support.design.widget.AppBarLayout>
<fragment
class="at.bitfire.davdroid.ui.AccountListFragment"
android:id="@+id/account_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/account_list"
app:layout_scrollFlags="scroll"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"

@ -37,7 +37,8 @@
android:theme="@style/toolbar_theme"
style="@style/toolbar_style"
app:navigationIcon="@drawable/ic_people_light"
app:title="CardDAV"/>
app:title="CardDAV"
android:elevation="2dp"/>
<ProgressBar
android:id="@+id/carddav_refreshing"
@ -76,7 +77,8 @@
android:theme="@style/toolbar_theme"
style="@style/toolbar_style"
app:navigationIcon="@drawable/ic_event_light"
app:title="CalDAV"/>
app:title="CalDAV"
android:elevation="2dp"/>
<ProgressBar
android:id="@+id/caldav_refreshing"

@ -9,21 +9,35 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/nav_about"
android:icon="@drawable/ic_info_dark"
android:title="@string/navigation_drawer_about"/>
<item
android:id="@+id/nav_website"
android:icon="@drawable/ic_home_dark"
android:title="@string/navigation_drawer_website"/>
<item
android:id="@+id/nav_donate"
android:icon="@drawable/ic_attach_money_dark"
android:title="@string/navigation_drawer_donate"/>
<item
android:id="@+id/nav_app_settings"
android:icon="@drawable/ic_settings_dark"
android:title="@string/navigation_drawer_app_settings"/>
android:title="@string/navigation_drawer_settings"/>
<item android:title="@string/navigation_drawer_external_links">
<menu>
<item
android:id="@+id/nav_website"
android:icon="@drawable/ic_home_dark"
android:title="@string/navigation_drawer_website"/>
<item
android:id="@+id/nav_faq"
android:icon="@drawable/ic_help_dark"
android:title="@string/navigation_drawer_faq"/>
<item
android:id="@+id/nav_forums"
android:icon="@drawable/ic_forum_dark"
android:title="@string/navigation_drawer_forums"/>
<item
android:id="@+id/nav_donate"
android:icon="@drawable/ic_attach_money_dark"
android:title="@string/navigation_drawer_donate"/>
<item
android:id="@+id/nav_about"
android:icon="@drawable/ic_info_dark"
android:title="@string/navigation_drawer_about"/>
</menu>
</item>
</menu>

@ -13,7 +13,7 @@
<item
android:id="@+id/help"
android:title="@string/help"
android:icon="@drawable/ic_help_light"
android:icon="@drawable/ic_help_dark"
app:showAsAction="always"
android:onClick="showHelp">
</item>

@ -20,20 +20,17 @@
<!-- startup dialogs -->
<string name="startup_dont_show_again">Don\'t show again</string>
<string name="startup_development_version">DAVdroid Preview Release</string>
<string name="startup_development_version_message">This is a development version of DAVdroid. Be aware that things
may not work as expected. Please give us constructive feedback to improve DAVdroid.</string>
<string name="startup_development_version_show_forums">Show forums</string>
<string name="startup_development_version_message">This is a development version of DAVdroid. Be aware that things may not work as expected. Please give us constructive feedback to improve DAVdroid.</string>
<string name="startup_development_version_give_feedback">Give feedback</string>
<string name="startup_donate">Open-Source Information</string>
<string name="startup_donate_message">We\'re happy that you use DAVdroid, which is open-source software (GPLv3). Because developing DAVdroid is hard work and took us thousands of working hours, please consider a donation.</string>
<string name="startup_donate_now">Show donation page</string>
<string name="startup_donate_later">Maybe later</string>
<string name="startup_google_play_accounts_removed">Play Store DRM bug information</string>
<string name="startup_google_play_accounts_removed_message">Under certain conditions, Play Store DRM may cause all DAVdroid accounts to be gone
after a reboot or after upgrading DAVdroid. If you\'re affected by this problem (and only then), please install \"DAVdroid JB Workaround\" from Play Store.</string>
<string name="startup_google_play_accounts_removed_message">Under certain conditions, Play Store DRM may cause all DAVdroid accounts to be gone after a reboot or after upgrading DAVdroid. If you\'re affected by this problem (and only then), please install \"DAVdroid JB Workaround\" from Play Store.</string>
<string name="startup_google_play_accounts_removed_more_info">More information</string>
<string name="startup_opentasks_not_installed">OpenTasks not installed</string>
<string name="startup_opentasks_not_installed_message">The OpenTasks app is not installed or not accessible, so DAVdroid won\'t be
able to synchronize task lists. You may have to re-install DAVdroid and then add your accounts again after installing OpenTasks.</string>
<string name="startup_opentasks_not_installed_message">The OpenTasks app is not installed or not accessible, so DAVdroid won\'t be able to synchronize task lists. Re-install DAVdroid and then add your accounts again after installing OpenTasks.</string>
<string name="startup_opentasks_not_installed_install">Install OpenTasks</string>
<!-- global settings -->
@ -48,9 +45,12 @@
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="navigation_drawer_subtitle">CalDAV/CardDAV Sync Adapter</string>
<string name="navigation_drawer_about">About / License</string>
<string name="navigation_drawer_donate">Donate</string>
<string name="navigation_drawer_app_settings">Settings</string>
<string name="navigation_drawer_settings">Settings</string>
<string name="navigation_drawer_external_links">External links</string>
<string name="navigation_drawer_website">Web site</string>
<string name="navigation_drawer_faq">FAQ</string>
<string name="navigation_drawer_forums">Community</string>
<string name="navigation_drawer_donate">Donate</string>
<string name="account_list_empty">Welcome to DAVdroid!\n\nYou can add a CalDAV/CardDAV account now.</string>
@ -157,9 +157,10 @@
<item quantity="one">Events more than one day in the past will be ignored</item>
<item quantity="other">Events more than %d days in the past will be ignored</item>
</plurals>
<string name="settings_sync_time_range_past_message">Events which are more than this number of days in the past (may be 0) will be ignored. Leave blank to synchronize all events.</string>
<string name="settings_sync_time_range_past_message">Events which are more than this number of days in the past will be ignored (may be 0). Leave blank to synchronize all events.</string>
<string name="settings_version_update">DAVdroid version update</string>
<string name="settings_version_update_warning">Internal settings have been updated. In case of problems, please uninstall DAVdroid and then install it again.</string>
<string name="settings_version_update_settings_updated">Internal settings have been updated.</string>
<string name="settings_version_update_install_hint">Problems? Uninstall DAVdroid, then re-install.</string>
<!-- collection management -->
<string name="create_addressbook">Create address book</string>

@ -19,6 +19,7 @@
<color name="light_green500">#8bc34a</color>
<color name="light_green700">#689f38</color>
<color name="orange400">#ffa726</color>
<color name="orangeA700">#ff6d00</color>
<color name="black">#000000</color>

Loading…
Cancel
Save