Update local task lists according to ServiceDB at sync
@ -111,12 +111,12 @@ public class SSLSocketFactoryCompat extends SSLSocketFactory {
|
||||
|
||||
private void upgradeTLS(SSLSocket ssl) {
|
||||
if (protocols != null) {
|
||||
Constants.log.debug("Setting allowed TLS protocols: " + TextUtils.join(", ", protocols));
|
||||
Constants.log.trace("Setting allowed TLS protocols: " + TextUtils.join(", ", protocols));
|
||||
ssl.setEnabledProtocols(protocols);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < 20 && cipherSuites != null) {
|
||||
Constants.log.debug("Setting allowed TLS ciphers: " + TextUtils.join(", ", cipherSuites));
|
||||
Constants.log.trace("Setting allowed TLS ciphers: " + TextUtils.join(", ", cipherSuites));
|
||||
ssl.setEnabledCipherSuites(cipherSuites);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import at.bitfire.dav4android.Property;
|
||||
import at.bitfire.dav4android.property.AddressbookDescription;
|
||||
import at.bitfire.dav4android.property.CalendarColor;
|
||||
import at.bitfire.dav4android.property.CalendarDescription;
|
||||
import at.bitfire.dav4android.property.CalendarTimezone;
|
||||
import at.bitfire.dav4android.property.CurrentUserPrivilegeSet;
|
||||
import at.bitfire.dav4android.property.DisplayName;
|
||||
import at.bitfire.dav4android.property.ResourceType;
|
||||
@ -22,7 +23,6 @@ import at.bitfire.dav4android.property.SupportedAddressData;
|
||||
import at.bitfire.dav4android.property.SupportedCalendarComponentSet;
|
||||
import lombok.ToString;
|
||||
import at.bitfire.davdroid.model.ServiceDB.*;
|
||||
import okhttp3.MediaType;
|
||||
|
||||
@ToString
|
||||
public class CollectionInfo {
|
||||
@ -40,11 +40,12 @@ public class CollectionInfo {
|
||||
public String displayName, description;
|
||||
public Integer color;
|
||||
|
||||
public Integer vCardVersion;
|
||||
|
||||
public String timeZone;
|
||||
public Boolean supportsVEVENT;
|
||||
public Boolean supportsVTODO;
|
||||
|
||||
public boolean selected;
|
||||
|
||||
// non-persistent properties
|
||||
public boolean confirmed;
|
||||
|
||||
@ -83,15 +84,6 @@ public class CollectionInfo {
|
||||
if (addressbookDescription != null)
|
||||
info.description = addressbookDescription.description;
|
||||
|
||||
SupportedAddressData addressData = (SupportedAddressData)dav.properties.get(SupportedAddressData.NAME);
|
||||
if (addressData != null) {
|
||||
boolean vCard4 = false;
|
||||
for (MediaType contentType : addressData.types)
|
||||
if ("text/vcard".equals(contentType.type()) && contentType.toString().contains("version=4.0"))
|
||||
vCard4 = true;
|
||||
info.vCardVersion = vCard4 ? 4 : 3;
|
||||
}
|
||||
|
||||
} else if (info.type == Type.CALENDAR) {
|
||||
CalendarDescription calendarDescription = (CalendarDescription)dav.properties.get(CalendarDescription.NAME);
|
||||
if (calendarDescription != null)
|
||||
@ -101,6 +93,10 @@ public class CollectionInfo {
|
||||
if (calendarColor != null)
|
||||
info.color = calendarColor.color;
|
||||
|
||||
CalendarTimezone timeZone = (CalendarTimezone)dav.properties.get(CalendarTimezone.NAME);
|
||||
if (timeZone != null)
|
||||
info.timeZone = timeZone.vTimeZone;
|
||||
|
||||
info.supportsVEVENT = info.supportsVTODO = true;
|
||||
SupportedCalendarComponentSet supportedCalendarComponentSet = (SupportedCalendarComponentSet)dav.properties.get(SupportedCalendarComponentSet.NAME);
|
||||
if (supportedCalendarComponentSet != null) {
|
||||
@ -120,12 +116,13 @@ public class CollectionInfo {
|
||||
info.displayName = values.getAsString(Collections.DISPLAY_NAME);
|
||||
info.description = values.getAsString(Collections.DESCRIPTION);
|
||||
|
||||
info.vCardVersion = values.getAsInteger(Collections.VCARD_VERSION);
|
||||
|
||||
info.color = values.getAsInteger(Collections.COLOR);
|
||||
|
||||
info.timeZone = values.getAsString(Collections.TIME_ZONE);
|
||||
info.supportsVEVENT = booleanField(values, Collections.SUPPORTS_VEVENT);
|
||||
info.supportsVTODO = booleanField(values, Collections.SUPPORTS_VTODO);
|
||||
|
||||
info.selected = booleanField(values, Collections.SELECTED);
|
||||
return info;
|
||||
}
|
||||
|
||||
@ -134,14 +131,15 @@ public class CollectionInfo {
|
||||
values.put(Collections.URL, url);
|
||||
values.put(Collections.DISPLAY_NAME, displayName);
|
||||
values.put(Collections.DESCRIPTION, description);
|
||||
|
||||
values.put(Collections.VCARD_VERSION, vCardVersion);
|
||||
|
||||
values.put(Collections.COLOR, color);
|
||||
|
||||
values.put(Collections.TIME_ZONE, timeZone);
|
||||
if (supportsVEVENT != null)
|
||||
values.put(Collections.SUPPORTS_VEVENT, supportsVEVENT ? 1 : 0);
|
||||
if (supportsVTODO != null)
|
||||
values.put(Collections.SUPPORTS_VTODO, supportsVTODO ? 1 : 0);
|
||||
|
||||
values.put(Collections.SELECTED, selected);
|
||||
return values;
|
||||
}
|
||||
|
||||
|
@ -8,14 +8,12 @@
|
||||
|
||||
package at.bitfire.davdroid.model;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.os.Build;
|
||||
|
||||
import at.bitfire.davdroid.Constants;
|
||||
import at.bitfire.davdroid.ui.setup.DavResourceFinder;
|
||||
|
||||
public class ServiceDB {
|
||||
|
||||
@ -51,12 +49,15 @@ public class ServiceDB {
|
||||
DISPLAY_NAME = "displayName",
|
||||
DESCRIPTION = "description",
|
||||
COLOR = "color",
|
||||
VCARD_VERSION = "vCardVersion",
|
||||
TIME_ZONE = "timezone",
|
||||
SUPPORTS_VEVENT = "supportsVEVENT",
|
||||
SUPPORTS_VTODO = "supportsVTODO";
|
||||
SUPPORTS_VTODO = "supportsVTODO",
|
||||
SELECTED = "selected";
|
||||
|
||||
public static String[] _COLUMNS = new String[] {
|
||||
ID, SERVICE_ID, URL, DISPLAY_NAME, DESCRIPTION, COLOR, VCARD_VERSION, SUPPORTS_VEVENT, SUPPORTS_VTODO
|
||||
ID, SERVICE_ID, URL, DISPLAY_NAME, DESCRIPTION, COLOR,
|
||||
TIME_ZONE, SUPPORTS_VEVENT, SUPPORTS_VTODO,
|
||||
SELECTED
|
||||
};
|
||||
}
|
||||
|
||||
@ -105,9 +106,10 @@ public class ServiceDB {
|
||||
Collections.DISPLAY_NAME + " TEXT NULL," +
|
||||
Collections.DESCRIPTION + " TEXT NULL," +
|
||||
Collections.COLOR + " INTEGER NULL," +
|
||||
Collections.VCARD_VERSION + " INTEGER NULL," +
|
||||
Collections.TIME_ZONE + " TEXt NULL," +
|
||||
Collections.SUPPORTS_VEVENT + " INTEGER NULL," +
|
||||
Collections.SUPPORTS_VTODO + " INTEGER NULL" +
|
||||
Collections.SUPPORTS_VTODO + " INTEGER NULL," +
|
||||
Collections.SELECTED + " INTEGER DEFAULT 0 NOT NULL" +
|
||||
")");
|
||||
db.execSQL("CREATE UNIQUE INDEX collections_service_url ON " + Collections._TABLE + "(" + Collections.SERVICE_ID + "," + Collections.URL + ")");
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import at.bitfire.davdroid.Constants;
|
||||
import at.bitfire.davdroid.model.CollectionInfo;
|
||||
import at.bitfire.ical4android.AndroidCalendar;
|
||||
import at.bitfire.ical4android.AndroidCalendarFactory;
|
||||
import at.bitfire.ical4android.BatchOperation;
|
||||
@ -69,17 +70,17 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
|
||||
}
|
||||
|
||||
@TargetApi(15)
|
||||
public static Uri create(Account account, ContentResolver resolver, ServerInfo.ResourceInfo info) throws CalendarStorageException {
|
||||
public static Uri create(Account account, ContentResolver resolver, CollectionInfo info) throws CalendarStorageException {
|
||||
@Cleanup("release") ContentProviderClient provider = resolver.acquireContentProviderClient(CalendarContract.AUTHORITY);
|
||||
if (provider == null)
|
||||
throw new CalendarStorageException("Couldn't acquire ContentProviderClient for " + CalendarContract.AUTHORITY);
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(Calendars.NAME, info.getUrl());
|
||||
values.put(Calendars.CALENDAR_DISPLAY_NAME, info.getTitle());
|
||||
values.put(Calendars.NAME, info.url);
|
||||
values.put(Calendars.CALENDAR_DISPLAY_NAME, info.displayName);
|
||||
values.put(Calendars.CALENDAR_COLOR, info.color != null ? info.color : defaultColor);
|
||||
|
||||
if (info.isReadOnly())
|
||||
if (info.readOnly)
|
||||
values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_READ);
|
||||
else {
|
||||
values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER);
|
||||
@ -90,8 +91,8 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
|
||||
values.put(Calendars.OWNER_ACCOUNT, account.name);
|
||||
values.put(Calendars.SYNC_EVENTS, 1);
|
||||
values.put(Calendars.VISIBLE, 1);
|
||||
if (!TextUtils.isEmpty(info.timezone)) {
|
||||
VTimeZone timeZone = DateUtils.parseVTimeZone(info.timezone);
|
||||
if (!TextUtils.isEmpty(info.timeZone)) {
|
||||
VTimeZone timeZone = DateUtils.parseVTimeZone(info.timeZone);
|
||||
if (timeZone != null && timeZone.getTimeZoneId() != null)
|
||||
values.put(Calendars.CALENDAR_TIME_ZONE, DateUtils.findAndroidTimezoneID(timeZone.getTimeZoneId().getValue()));
|
||||
}
|
||||
|
@ -55,15 +55,23 @@ public class LocalTaskList extends AndroidTaskList implements LocalCollection {
|
||||
}
|
||||
|
||||
public static Uri create(Account account, TaskProvider provider, CollectionInfo info) throws CalendarStorageException {
|
||||
ContentValues values = valuesFromCollectionInfo(info);
|
||||
values.put(TaskLists.OWNER, account.name);
|
||||
return create(account, provider, values);
|
||||
}
|
||||
|
||||
public void update(CollectionInfo info) throws CalendarStorageException {
|
||||
update(valuesFromCollectionInfo(info));
|
||||
}
|
||||
|
||||
private static ContentValues valuesFromCollectionInfo(CollectionInfo info) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(TaskLists._SYNC_ID, info.url);
|
||||
values.put(TaskLists.LIST_NAME, info.displayName);
|
||||
values.put(TaskLists.LIST_COLOR, info.color != null ? info.color : defaultColor);
|
||||
values.put(TaskLists.OWNER, account.name);
|
||||
values.put(TaskLists.SYNC_ENABLED, 1);
|
||||
values.put(TaskLists.VISIBLE, 1);
|
||||
|
||||
return create(account, provider, values);
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2013 – 2015 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.resource;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor(suppressConstructorProperties=true)
|
||||
@Data
|
||||
public class ServerInfo implements Serializable {
|
||||
final private URI baseURI;
|
||||
final private String userName, password;
|
||||
final boolean authPreemptive;
|
||||
|
||||
private String logs;
|
||||
|
||||
private ResourceInfo
|
||||
addressBooks[] = new ResourceInfo[0],
|
||||
calendars[] = new ResourceInfo[0],
|
||||
taskLists[] = new ResourceInfo[0];
|
||||
|
||||
|
||||
public boolean hasEnabledCalendars() {
|
||||
for (ResourceInfo calendar : calendars)
|
||||
if (calendar.enabled)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return addressBooks.length == 0 && calendars.length == 0 && taskLists.length == 0;
|
||||
}
|
||||
|
||||
|
||||
@RequiredArgsConstructor(suppressConstructorProperties=true)
|
||||
@Data
|
||||
public static class ResourceInfo implements Serializable {
|
||||
|
||||
public enum Type {
|
||||
ADDRESS_BOOK,
|
||||
CALENDAR
|
||||
}
|
||||
|
||||
boolean enabled = false;
|
||||
|
||||
final Type type;
|
||||
final boolean readOnly;
|
||||
|
||||
final String url, // absolute URL of resource
|
||||
title,
|
||||
description;
|
||||
final Integer color;
|
||||
|
||||
/** full VTIMEZONE definition (not the TZ ID) */
|
||||
String timezone;
|
||||
|
||||
|
||||
// copy constructor
|
||||
|
||||
@Override
|
||||
public ResourceInfo clone() {
|
||||
return new ResourceInfo(this);
|
||||
}
|
||||
|
||||
private ResourceInfo(ResourceInfo src) {
|
||||
enabled = src.enabled;
|
||||
type = src.type;
|
||||
readOnly = src.readOnly;
|
||||
|
||||
url = src.url;
|
||||
title = src.title;
|
||||
description = src.description;
|
||||
color = src.color;
|
||||
|
||||
timezone = src.timezone;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -36,7 +36,6 @@ import java.util.List;
|
||||
import at.bitfire.davdroid.Constants;
|
||||
import at.bitfire.davdroid.R;
|
||||
import at.bitfire.davdroid.resource.LocalAddressBook;
|
||||
import at.bitfire.davdroid.resource.ServerInfo;
|
||||
import at.bitfire.vcard4android.ContactsStorageException;
|
||||
import lombok.Cleanup;
|
||||
|
||||
|
@ -25,10 +25,8 @@ import java.util.*;
|
||||
|
||||
import at.bitfire.davdroid.Constants;
|
||||
import at.bitfire.davdroid.model.CollectionInfo;
|
||||
import at.bitfire.davdroid.model.ServiceDB;
|
||||
import at.bitfire.davdroid.model.ServiceDB.*;
|
||||
import at.bitfire.davdroid.model.ServiceDB.Collections;
|
||||
import at.bitfire.davdroid.resource.LocalTask;
|
||||
import at.bitfire.davdroid.resource.LocalTaskList;
|
||||
import at.bitfire.ical4android.CalendarStorageException;
|
||||
import at.bitfire.ical4android.TaskProvider;
|
||||
@ -75,7 +73,7 @@ public class TasksSyncAdapterService extends Service {
|
||||
if (provider == null)
|
||||
throw new CalendarStorageException("Couldn't access OpenTasks provider");
|
||||
|
||||
syncLocalTaskLists(provider, account);
|
||||
updateLocalTaskLists(provider, account);
|
||||
|
||||
for (LocalTaskList taskList : (LocalTaskList[])LocalTaskList.find(account, provider, LocalTaskList.Factory.INSTANCE, null, null)) {
|
||||
Constants.log.info("Synchronizing task list #" + taskList.getId() + ", URL: " + taskList.getSyncId());
|
||||
@ -84,12 +82,14 @@ public class TasksSyncAdapterService extends Service {
|
||||
}
|
||||
} catch (CalendarStorageException e) {
|
||||
Constants.log.error("Couldn't enumerate local task lists", e);
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
|
||||
Constants.log.info("Task sync complete");
|
||||
}
|
||||
|
||||
private void syncLocalTaskLists(TaskProvider provider, Account account) throws CalendarStorageException {
|
||||
private void updateLocalTaskLists(TaskProvider provider, Account account) throws CalendarStorageException {
|
||||
long service = getService(account);
|
||||
|
||||
// enumerate remote and local task lists
|
||||
@ -99,13 +99,17 @@ public class TasksSyncAdapterService extends Service {
|
||||
// delete obsolete local task lists
|
||||
for (LocalTaskList list : local) {
|
||||
String url = list.getSyncId();
|
||||
Constants.log.debug("Checking local task list {} {}", list.getId(), url);
|
||||
if (!remote.containsKey(url)) {
|
||||
Constants.log.debug("Deleting local task list {}", url);
|
||||
Constants.log.debug("Deleting obsolete local task list {}", url);
|
||||
list.delete();
|
||||
} else
|
||||
// we already have a local task list for this remote collection
|
||||
} else {
|
||||
// remote CollectionInfo found for this local collection, update data
|
||||
CollectionInfo info = remote.get(url);
|
||||
Constants.log.debug("Updating local task list {} with {}", url, info);
|
||||
list.update(info);
|
||||
// we already have a local task list for this remote collection, don't take into consideration anymore
|
||||
remote.remove(url);
|
||||
}
|
||||
}
|
||||
|
||||
// create new local task lists
|
||||
|
@ -31,6 +31,8 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.view.menu.MenuBuilder;
|
||||
import android.support.v7.view.menu.MenuPresenter;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.TextUtils;
|
||||
@ -40,7 +42,6 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
@ -58,13 +59,14 @@ import at.bitfire.davdroid.model.ServiceDB.OpenHelper;
|
||||
import at.bitfire.davdroid.model.ServiceDB.Services;
|
||||
import lombok.Cleanup;
|
||||
|
||||
public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenuItemClickListener, ServiceConnection, DavService.RefreshingStatusListener, LoaderManager.LoaderCallbacks<AccountActivity.AccountInfo> {
|
||||
public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenuItemClickListener, LoaderManager.LoaderCallbacks<AccountActivity.AccountInfo> {
|
||||
|
||||
public static final String EXTRA_ACCOUNT_NAME = "account_name";
|
||||
|
||||
private String accountName;
|
||||
private AccountInfo accountInfo;
|
||||
private DavService.InfoBinder davService;
|
||||
|
||||
Toolbar tbCardDAV, tbCalDAV;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -78,29 +80,20 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
|
||||
|
||||
setContentView(R.layout.activity_account);
|
||||
|
||||
Toolbar toolbar = (Toolbar)findViewById(R.id.carddav_menu);
|
||||
toolbar.inflateMenu(R.menu.carddav_actions);
|
||||
toolbar.setOnMenuItemClickListener(this);
|
||||
// CardDAV toolbar
|
||||
tbCardDAV = (Toolbar)findViewById(R.id.carddav_menu);
|
||||
tbCardDAV.inflateMenu(R.menu.carddav_actions);
|
||||
tbCardDAV.setOnMenuItemClickListener(this);
|
||||
|
||||
toolbar = (Toolbar)findViewById(R.id.caldav_menu);
|
||||
toolbar.inflateMenu(R.menu.caldav_actions);
|
||||
toolbar.setOnMenuItemClickListener(this);
|
||||
// CalDAV toolbar
|
||||
tbCalDAV = (Toolbar)findViewById(R.id.caldav_menu);
|
||||
tbCalDAV.inflateMenu(R.menu.caldav_actions);
|
||||
tbCalDAV.setOnMenuItemClickListener(this);
|
||||
|
||||
// load CardDAV/CalDAV collections
|
||||
getLoaderManager().initLoader(0, getIntent().getExtras(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
bindService(new Intent(this, DavService.class), this, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
unbindService(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.activity_account, menu);
|
||||
@ -153,26 +146,6 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
|
||||
}
|
||||
|
||||
|
||||
/* SERVICE CONNECTION */
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
davService = (DavService.InfoBinder)service;
|
||||
davService.addRefreshingStatusListener(this, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
davService.removeRefreshingStatusListener(this);
|
||||
davService = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDavRefreshStatusChanged(long id, boolean refreshing) {
|
||||
getLoaderManager().restartLoader(0, getIntent().getExtras(), this);
|
||||
}
|
||||
|
||||
|
||||
/* LOADERS AND LOADED DATA */
|
||||
|
||||
public static class AccountInfo {
|
||||
@ -192,7 +165,7 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<AccountInfo> loader, AccountInfo info) {
|
||||
public void onLoadFinished(Loader<AccountInfo> loader, final AccountInfo info) {
|
||||
accountInfo = info;
|
||||
|
||||
CardView card = (CardView)findViewById(R.id.carddav);
|
||||
@ -249,6 +222,7 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
davService = (DavService.InfoBinder)service;
|
||||
davService.addRefreshingStatusListener(this, false);
|
||||
forceLoad();
|
||||
}
|
||||
|
||||
|
@ -43,18 +43,12 @@ import at.bitfire.davdroid.model.ServiceDB.Services;
|
||||
import lombok.Cleanup;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
public class AccountListFragment extends ListFragment implements OnAccountsUpdateListener, LoaderManager.LoaderCallbacks<List<AccountListFragment.AccountInfo>>, AdapterView.OnItemClickListener {
|
||||
|
||||
private AccountManager accountManager;
|
||||
private DavService.InfoBinder davService;
|
||||
public class AccountListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<List<AccountListFragment.AccountInfo>>, AdapterView.OnItemClickListener {
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
setListAdapter(new AccountListAdapter(getContext()));
|
||||
|
||||
accountManager = AccountManager.get(getContext());
|
||||
accountManager.addOnAccountsUpdatedListener(this, null, false);
|
||||
|
||||
return inflater.inflate(R.layout.account_list, container, false);
|
||||
}
|
||||
|
||||
@ -68,13 +62,6 @@ public class AccountListFragment extends ListFragment implements OnAccountsUpdat
|
||||
list.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
accountManager.removeOnAccountsUpdatedListener(this);
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
AccountInfo info = (AccountInfo)getListAdapter().getItem(position);
|
||||
@ -85,12 +72,6 @@ public class AccountListFragment extends ListFragment implements OnAccountsUpdat
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onAccountsUpdated(Account[] accounts) {
|
||||
getLoaderManager().restartLoader(0, null, this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Loader<List<AccountInfo>> onCreateLoader(int id, Bundle args) {
|
||||
return new AccountLoader(getContext());
|
||||
@ -99,10 +80,8 @@ public class AccountListFragment extends ListFragment implements OnAccountsUpdat
|
||||
@Override
|
||||
public void onLoadFinished(Loader<List<AccountInfo>> loader, List<AccountInfo> accounts) {
|
||||
AccountListAdapter adapter = (AccountListAdapter)getListAdapter();
|
||||
if (adapter != null) {
|
||||
adapter.clear();
|
||||
adapter.addAll(accounts);
|
||||
}
|
||||
adapter.clear();
|
||||
adapter.addAll(accounts);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -113,13 +92,10 @@ public class AccountListFragment extends ListFragment implements OnAccountsUpdat
|
||||
@RequiredArgsConstructor
|
||||
public static class AccountInfo {
|
||||
final Account account;
|
||||
boolean isRefreshing;
|
||||
Long cardDavService, calDavService;
|
||||
}
|
||||
|
||||
|
||||
static class AccountListAdapter extends ArrayAdapter<AccountInfo> {
|
||||
|
||||
public AccountListAdapter(Context context) {
|
||||
super(context, R.layout.account_list_item);
|
||||
}
|
||||
@ -141,10 +117,9 @@ public class AccountListFragment extends ListFragment implements OnAccountsUpdat
|
||||
tv.setVisibility(info.calDavService != null ? View.VISIBLE : View.GONE);
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class AccountLoader extends AsyncTaskLoader<List<AccountInfo>> {
|
||||
private static class AccountLoader extends AsyncTaskLoader<List<AccountInfo>> implements OnAccountsUpdateListener {
|
||||
private final AccountManager accountManager;
|
||||
private final OpenHelper dbHelper;
|
||||
|
||||
@ -156,12 +131,21 @@ public class AccountListFragment extends ListFragment implements OnAccountsUpdat
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
accountManager.addOnAccountsUpdatedListener(this, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStopLoading() {
|
||||
accountManager.removeOnAccountsUpdatedListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccountsUpdated(Account[] accounts) {
|
||||
forceLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccountInfo> loadInBackground() {
|
||||
Constants.log.info("AccountLoader RUNNING");
|
||||
List<AccountInfo> accounts = new LinkedList<>();
|
||||
try {
|
||||
SQLiteDatabase db = dbHelper.getReadableDatabase();
|
||||
|
@ -112,7 +112,8 @@ public class AccountDetailsFragment extends Fragment {
|
||||
|
||||
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
|
||||
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
|
||||
}
|
||||
} else
|
||||
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 0);
|
||||
|
||||
if (config.calDAV != null) {
|
||||
long id = insertService(db, accountName, Services.SERVICE_CALDAV, config.calDAV);
|
||||
@ -125,6 +126,9 @@ public class AccountDetailsFragment extends Fragment {
|
||||
// TODO check for tasks availability
|
||||
ContentResolver.setIsSyncable(account, TaskProvider.ProviderName.OpenTasks.authority, 1);
|
||||
ContentResolver.setSyncAutomatically(account, TaskProvider.ProviderName.OpenTasks.authority, true);
|
||||
} else {
|
||||
ContentResolver.setIsSyncable(account, CalendarContract.AUTHORITY, 0);
|
||||
ContentResolver.setIsSyncable(account, TaskProvider.ProviderName.OpenTasks.authority, 0);
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 661 B |
Before Width: | Height: | Size: 321 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 804 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 671 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 488 B |
Before Width: | Height: | Size: 245 B |
Before Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-nodpi/sky_birds.png
Normal file
After Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 813 B |
Before Width: | Height: | Size: 341 B |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 649 B |
Before Width: | Height: | Size: 578 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 441 B |
Before Width: | Height: | Size: 2.6 KiB |
@ -9,23 +9,36 @@
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="8dp">
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
<android.support.v7.widget.AppCompatRadioButton
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
tools:text="My Address Book"/>
|
||||
android:layout_marginRight="4dp"
|
||||
android:id="@+id/checkBox"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
tools:text="Address Book Description"/>
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
tools:text="My Address Book"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
tools:text="Address Book Description"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -15,6 +15,11 @@
|
||||
android:padding="8dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="4dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -1,95 +0,0 @@
|
||||
<!--
|
||||
~ Copyright (c) 2013 – 2015 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
|
||||
-->
|
||||
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="20dp"
|
||||
tools:context=".MainActivity" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_store_specific"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:layout_marginBottom="40dp"
|
||||
android:linksClickable="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_welcome"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_welcome"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_what_is_davdroid"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_what_is_davdroid_html"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:linksClickable="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
<TextView
|
||||
android:id="@+id/text_how_to_setup"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_how_to_setup_html"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:linksClickable="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
<TextView
|
||||
android:id="@+id/text_support"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_support_html"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:linksClickable="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
<TextView
|
||||
android:id="@+id/text_open_source_disclaimer"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_open_source_disclaimer_html"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:linksClickable="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
<TextView
|
||||
android:id="@+id/text_license"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_license_html"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:linksClickable="true" />
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_translation_info"
|
||||
android:layout_marginBottom="20dp" />
|
||||
<TextView
|
||||
android:id="@+id/text_libraries_heading"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_used_libraries_heading"
|
||||
android:linksClickable="true" />
|
||||
<TextView
|
||||
android:id="@+id/text_libraries_list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:linksClickable="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2013 – 2015 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
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:onClick="addAccount" android:title="@string/setup_add_account" android:showAsAction="always" android:icon="@drawable/ic_action_new_account"/>
|
||||
<item android:onClick="showSyncSettings" android:title="@string/main_manage_accounts" android:showAsAction="always" android:icon="@drawable/show_sync_settings"/>
|
||||
<item android:onClick="showSettings" android:title="@string/settings_title" android:showAsAction="never" android:icon="@drawable/ic_action_settings"/>
|
||||
<item android:onClick="showDebugInfo" android:title="@string/main_show_debug_info" android:showAsAction="never" />
|
||||
<item android:onClick="showWebsite" android:title="@string/help" android:showAsAction="ifRoom" android:icon="@drawable/view_website"/>
|
||||
</menu>
|
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2013 – 2015 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
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<item
|
||||
android:id="@+id/next"
|
||||
android:icon="@drawable/navigation_forward"
|
||||
android:showAsAction="always|withText"
|
||||
android:title="@string/next">
|
||||
</item>
|
||||
|
||||
</menu>
|
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2013 – 2015 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
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/skip"
|
||||
android:icon="@drawable/navigation_skip"
|
||||
android:showAsAction="always|withText"
|
||||
android:title="@string/skip">
|
||||
</item>
|
||||
|
||||
</menu>
|