Update local task lists according to ServiceDB at sync

pull/2/head
Ricki Hirner 9 years ago
parent 89a516bfd1
commit 5025a61cd1

@ -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();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 671 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

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>
Loading…
Cancel
Save