mirror of
https://github.com/etesync/android
synced 2025-01-11 00:01:12 +00:00
Service database
* HttpClient: authentication that is limited to a host name is never preemptive * DavResourceFinder: service configuration == null means that this service is not available * new SQLite database for CalDAV/CardDAV services * added AccountDetailsFragment, which asks for account name and then finishes account creation * updated AccountListFragment
This commit is contained in:
parent
85a6b68a56
commit
ff901ce91f
@ -10,19 +10,15 @@ package at.bitfire.davdroid;
|
||||
|
||||
import android.test.InstrumentationTestCase;
|
||||
|
||||
import okhttp3.ConnectionSpec;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.TlsVersion;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
|
||||
public class HttpClientTest extends InstrumentationTestCase {
|
||||
|
||||
MockWebServer server;
|
||||
|
@ -10,8 +10,6 @@ package at.bitfire.davdroid;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -19,6 +17,8 @@ import java.net.Socket;
|
||||
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
|
||||
public class SSLSocketFactoryCompatTest extends TestCase {
|
||||
|
||||
SSLSocketFactoryCompat factory = new SSLSocketFactoryCompat(null);
|
||||
|
@ -2,17 +2,14 @@ package at.bitfire.davdroid.resource;
|
||||
|
||||
import android.test.InstrumentationTestCase;
|
||||
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import at.bitfire.dav4android.exception.DavException;
|
||||
import at.bitfire.dav4android.exception.HttpException;
|
||||
import at.bitfire.davdroid.Constants;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
|
||||
public class DavResourceFinderTest extends InstrumentationTestCase {
|
||||
|
||||
|
@ -114,8 +114,7 @@
|
||||
<activity
|
||||
android:name=".ui.setup.LoginActivity"
|
||||
android:label="@string/login_title"
|
||||
android:parentActivityName=".ui.AccountsActivity"
|
||||
android:noHistory="true">
|
||||
android:parentActivityName=".ui.AccountsActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
</intent-filter>
|
||||
|
@ -11,22 +11,11 @@ package at.bitfire.davdroid;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import lombok.NonNull;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.Credentials;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.tls.OkHostnameVerifier;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.net.CookieManager;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
@ -34,7 +23,15 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import at.bitfire.dav4android.BasicDigestAuthenticator;
|
||||
import de.duenndns.ssl.MemorizingTrustManager;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import okhttp3.Credentials;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.tls.OkHostnameVerifier;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
|
||||
public class HttpClient {
|
||||
private static final int MAX_LOG_LINE_LENGTH = 85;
|
||||
@ -87,29 +84,12 @@ public class HttpClient {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static OkHttpClient addAuthentication(@NonNull OkHttpClient httpClient, @NonNull String host, @NonNull String username, @NonNull String password, boolean preemptive) {
|
||||
public static OkHttpClient addAuthentication(@NonNull OkHttpClient httpClient, @NonNull String host, @NonNull String username, @NonNull String password) {
|
||||
return httpClient.newBuilder()
|
||||
.authenticator(new BasicDigestAuthenticator(host, username, password))
|
||||
.build();
|
||||
}
|
||||
|
||||
//@NonNull final Logger log
|
||||
|
||||
/**
|
||||
* Creates a new HttpClient (based on another one) which can be used to download external resources:
|
||||
* 1. it does not use preemptive authentication
|
||||
* 2. it only authenticates against a given host
|
||||
* @param httpClient user name and password from this client will be used
|
||||
* @param host authentication will be restricted to this host
|
||||
*/
|
||||
/*public HttpClient(Logger log, HttpClient client, String host) {
|
||||
this(log, client.context);
|
||||
|
||||
username = client.username;
|
||||
password = client.password;
|
||||
setAuthenticator(new BasicDigestAuthenticator(host, username, password));
|
||||
}*/
|
||||
|
||||
public static OkHttpClient addLogger(@NonNull OkHttpClient httpClient, @NonNull final Logger logger) {
|
||||
// enable verbose logs, if requested
|
||||
if (logger.isTraceEnabled()) {
|
||||
|
@ -18,6 +18,7 @@ import org.xbill.DNS.TXTRecord;
|
||||
import org.xbill.DNS.Type;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -84,7 +85,11 @@ public class DavResourceFinder {
|
||||
cardDavConfig = findInitialConfiguration(Service.CARDDAV),
|
||||
calDavConfig = findInitialConfiguration(Service.CALDAV);
|
||||
|
||||
return new Configuration(cardDavConfig, calDavConfig, log.toString());
|
||||
return new Configuration(
|
||||
credentials.getUserName(), credentials.getPassword(), credentials.isAuthPreemptive(),
|
||||
cardDavConfig, calDavConfig,
|
||||
log.toString()
|
||||
);
|
||||
}
|
||||
|
||||
protected Configuration.ServiceInfo findInitialConfiguration(@NonNull Service service) {
|
||||
@ -133,7 +138,9 @@ public class DavResourceFinder {
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
// return config or null if config doesn't contain useful information
|
||||
boolean serviceAvailable = config.principal != null || !config.homeSets.isEmpty() || !config.collections.isEmpty();
|
||||
return serviceAvailable ? config : null;
|
||||
}
|
||||
|
||||
protected void checkUserGivenURL(@NonNull HttpUrl baseURL, @NonNull Service service, @NonNull Configuration.ServiceInfo config) {
|
||||
@ -405,27 +412,31 @@ public class DavResourceFinder {
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@ToString(exclude="logs")
|
||||
public static class Configuration {
|
||||
public static class Configuration implements Serializable {
|
||||
|
||||
public final String userName, password;
|
||||
public final boolean preemptive;
|
||||
|
||||
public final ServiceInfo cardDAV;
|
||||
public final ServiceInfo calDAV;
|
||||
|
||||
public final String logs;
|
||||
|
||||
|
||||
@ToString
|
||||
public static class ServiceInfo {
|
||||
public static class ServiceInfo implements Serializable {
|
||||
@Getter
|
||||
HttpUrl principal;
|
||||
|
||||
@Getter
|
||||
Set<HttpUrl> homeSets = new HashSet<>();
|
||||
final Set<HttpUrl> homeSets = new HashSet<>();
|
||||
|
||||
@Getter
|
||||
Map<HttpUrl, Collection> collections = new HashMap<>();
|
||||
final Map<HttpUrl, Collection> collections = new HashMap<>();
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Collection {
|
||||
public static class Collection implements Serializable {
|
||||
public enum Type {
|
||||
ADDRESS_BOOK,
|
||||
CALENDAR
|
||||
@ -434,7 +445,7 @@ public class DavResourceFinder {
|
||||
final Type type;
|
||||
final boolean readOnly;
|
||||
|
||||
final String title, description;
|
||||
final String displayName, description;
|
||||
final Integer color;
|
||||
|
||||
/**
|
||||
|
@ -109,11 +109,11 @@ public class AccountSettings {
|
||||
}
|
||||
|
||||
|
||||
public static Bundle createBundle(ServerInfo serverInfo) {
|
||||
public static Bundle initialUserData(String userName, boolean preemptive) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(KEY_SETTINGS_VERSION, String.valueOf(CURRENT_VERSION));
|
||||
bundle.putString(KEY_USERNAME, serverInfo.getUserName());
|
||||
bundle.putString(KEY_AUTH_PREEMPTIVE, Boolean.toString(serverInfo.isAuthPreemptive()));
|
||||
bundle.putString(KEY_USERNAME, userName);
|
||||
bundle.putString(KEY_AUTH_PREEMPTIVE, Boolean.toString(preemptive));
|
||||
return bundle;
|
||||
}
|
||||
|
||||
|
@ -279,7 +279,7 @@ public class ContactsSyncManager extends SyncManager {
|
||||
OkHttpClient resourceClient = HttpClient.create(context);
|
||||
|
||||
// authenticate only against a certain host, and only upon request
|
||||
resourceClient = HttpClient.addAuthentication(resourceClient, baseUrl.host(), settings.username(), settings.password(), false);
|
||||
resourceClient = HttpClient.addAuthentication(resourceClient, baseUrl.host(), settings.username(), settings.password());
|
||||
|
||||
// allow redirects
|
||||
resourceClient = resourceClient.newBuilder()
|
||||
|
102
app/src/main/java/at/bitfire/davdroid/syncadapter/ServiceDB.java
Normal file
102
app/src/main/java/at/bitfire/davdroid/syncadapter/ServiceDB.java
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import at.bitfire.davdroid.Constants;
|
||||
import at.bitfire.davdroid.resource.DavResourceFinder;
|
||||
|
||||
public class ServiceDB {
|
||||
|
||||
public static class Services {
|
||||
public static final String
|
||||
_TABLE = "services",
|
||||
ID = "_id",
|
||||
ACCOUNT_NAME = "account_name",
|
||||
SERVICE = "service",
|
||||
PRINCIPAL = "principal",
|
||||
LAST_REFRESH = "last_refresh";
|
||||
|
||||
// allowed values for SERVICE column
|
||||
public static final String
|
||||
SERVICE_CALDAV = "caldav",
|
||||
SERVICE_CARDDAV = "carddav";
|
||||
}
|
||||
|
||||
public static class HomeSets {
|
||||
public static final String
|
||||
_TABLE = "homesets",
|
||||
ID = "_id",
|
||||
SERVICE_ID = "service_id",
|
||||
URL = "url";
|
||||
}
|
||||
|
||||
public static class Collections {
|
||||
public static final String
|
||||
_TABLE = "collections",
|
||||
ID = "_id",
|
||||
SERVICE_ID = "service_id",
|
||||
URL = "url",
|
||||
DISPLAY_NAME = "display_name",
|
||||
DESCRIPTION = "description";
|
||||
|
||||
public static ContentValues fromCollection(DavResourceFinder.Configuration.Collection collection) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(DISPLAY_NAME, collection.getDisplayName());
|
||||
values.put(DESCRIPTION, collection.getDescription());
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class OpenHelper extends SQLiteOpenHelper {
|
||||
private static final String DATABASE_NAME = "services.db";
|
||||
private static final int DATABASE_VERSION = 1;
|
||||
|
||||
public OpenHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
Constants.log.info("Creating services database");
|
||||
|
||||
db.execSQL("CREATE TABLE " + Services._TABLE + "(" +
|
||||
Services.ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
Services.ACCOUNT_NAME + " TEXT NOT NULL," +
|
||||
Services.SERVICE + " TEXT NOT NULL," +
|
||||
Services.PRINCIPAL + " TEXT NULL, " +
|
||||
Services.LAST_REFRESH + " INTEGER NULL" +
|
||||
")");
|
||||
|
||||
db.execSQL("CREATE TABLE " + HomeSets._TABLE + "(" +
|
||||
HomeSets.ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
HomeSets.SERVICE_ID + " INTEGER NOT NULL," +
|
||||
HomeSets.URL + " TEXT NOT NULL" +
|
||||
")");
|
||||
|
||||
db.execSQL("CREATE TABLE " + Collections._TABLE + "(" +
|
||||
Collections.ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
Collections.SERVICE_ID + " INTEGER NOT NULL," +
|
||||
Collections.URL + " TEXT NOT NULL," +
|
||||
Collections.DISPLAY_NAME + " TEXT NULL," +
|
||||
Collections.DESCRIPTION + " TEXT NULL" +
|
||||
")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -12,18 +12,30 @@ import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.OnAccountsUpdateListener;
|
||||
import android.content.Context;
|
||||
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;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import at.bitfire.davdroid.Constants;
|
||||
import at.bitfire.davdroid.R;
|
||||
import at.bitfire.davdroid.syncadapter.ServiceDB;
|
||||
import at.bitfire.davdroid.syncadapter.ServiceDB.*;
|
||||
import lombok.Cleanup;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
public class AccountListFragment extends ListFragment implements OnAccountsUpdateListener {
|
||||
public class AccountListFragment extends ListFragment implements OnAccountsUpdateListener, LoaderManager.LoaderCallbacks<List<AccountListFragment.AccountInfo>> {
|
||||
|
||||
protected AccountManager accountManager;
|
||||
|
||||
@ -32,11 +44,17 @@ public class AccountListFragment extends ListFragment implements OnAccountsUpdat
|
||||
setListAdapter(new AccountListAdapter(getContext()));
|
||||
|
||||
accountManager = AccountManager.get(getContext());
|
||||
accountManager.addOnAccountsUpdatedListener(this, null, true);
|
||||
accountManager.addOnAccountsUpdatedListener(this, null, false);
|
||||
|
||||
return inflater.inflate(R.layout.account_list, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
getLoaderManager().initLoader(0, getArguments(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
accountManager.removeOnAccountsUpdatedListener(this);
|
||||
@ -45,17 +63,35 @@ 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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<List<AccountInfo>> loader, List<AccountInfo> accounts) {
|
||||
AccountListAdapter adapter = (AccountListAdapter)getListAdapter();
|
||||
if (adapter != null) {
|
||||
adapter.clear();
|
||||
for (Account account : accounts)
|
||||
if (Constants.ACCOUNT_TYPE.equals(account.type))
|
||||
adapter.add(account);
|
||||
adapter.addAll(accounts);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<List<AccountInfo>> loader) {
|
||||
}
|
||||
|
||||
class AccountListAdapter extends ArrayAdapter<Account> {
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static class AccountInfo {
|
||||
final Account account;
|
||||
boolean hasCardDAV, hasCalDAV;
|
||||
}
|
||||
|
||||
static class AccountListAdapter extends ArrayAdapter<AccountInfo> {
|
||||
|
||||
public AccountListAdapter(Context context) {
|
||||
super(context, R.layout.account_list_item);
|
||||
@ -70,12 +106,66 @@ public class AccountListFragment extends ListFragment implements OnAccountsUpdat
|
||||
v = inflater.inflate(R.layout.account_list_item, parent, false);
|
||||
}
|
||||
|
||||
Account account = getItem(position);
|
||||
AccountInfo info = getItem(position);
|
||||
|
||||
TextView tvName = (TextView)v.findViewById(R.id.account_name);
|
||||
tvName.setText(account.name);
|
||||
TextView tv = (TextView)v.findViewById(R.id.account_name);
|
||||
tv.setText(info.account.name);
|
||||
|
||||
tv = (TextView)v.findViewById(R.id.carddav);
|
||||
tv.setVisibility(info.hasCardDAV ? View.VISIBLE : View.GONE);
|
||||
|
||||
tv = (TextView)v.findViewById(R.id.caldav);
|
||||
tv.setVisibility(info.hasCalDAV ? View.VISIBLE : View.GONE);
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
static class AccountLoader extends AsyncTaskLoader<List<AccountInfo>> {
|
||||
final AccountManager accountManager;
|
||||
final OpenHelper dbHelper;
|
||||
|
||||
public AccountLoader(Context context) {
|
||||
super(context);
|
||||
accountManager = AccountManager.get(context);
|
||||
dbHelper = new OpenHelper(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
forceLoad();
|
||||
}
|
||||
|
||||
@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.SERVICE },
|
||||
Services.ACCOUNT_NAME + "=?", new String[] { account.name },
|
||||
null, null, null);
|
||||
while (cursor.moveToNext()) {
|
||||
String service = cursor.getString(0);
|
||||
if (Services.SERVICE_CARDDAV.equals(service))
|
||||
info.hasCardDAV = true;
|
||||
if (Services.SERVICE_CALDAV.equals(service))
|
||||
info.hasCalDAV = true;
|
||||
}
|
||||
|
||||
accounts.add(info);
|
||||
}
|
||||
} finally {
|
||||
dbHelper.close();
|
||||
}
|
||||
return accounts;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ package at.bitfire.davdroid.ui;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Activity;
|
||||
import android.app.LoaderManager;
|
||||
import android.content.AsyncTaskLoader;
|
||||
import android.content.ContentResolver;
|
||||
@ -23,6 +22,7 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.CalendarContract;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@ -42,7 +42,7 @@ import at.bitfire.davdroid.Constants;
|
||||
import at.bitfire.davdroid.R;
|
||||
import at.bitfire.davdroid.syncadapter.AccountSettings;
|
||||
|
||||
public class DebugInfoActivity extends Activity implements LoaderManager.LoaderCallbacks<String> {
|
||||
public class DebugInfoActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<String> {
|
||||
public static final String
|
||||
KEY_EXCEPTION = "exception",
|
||||
KEY_LOGS = "logs",
|
||||
@ -67,7 +67,7 @@ public class DebugInfoActivity extends Activity implements LoaderManager.LoaderC
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.exception_details_activity, menu);
|
||||
getMenuInflater().inflate(R.menu.activity_debug_info, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.ui.setup;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.ContentValues;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import at.bitfire.davdroid.Constants;
|
||||
import at.bitfire.davdroid.R;
|
||||
import at.bitfire.davdroid.resource.DavResourceFinder;
|
||||
import at.bitfire.davdroid.syncadapter.AccountSettings;
|
||||
import at.bitfire.davdroid.syncadapter.ServiceDB.*;
|
||||
import lombok.Cleanup;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
public class AccountDetailsFragment extends Fragment {
|
||||
|
||||
private static final String KEY_CONFIG = "config";
|
||||
|
||||
public static AccountDetailsFragment newInstance(DavResourceFinder.Configuration config) {
|
||||
Bundle args = new Bundle(1);
|
||||
args.putSerializable(KEY_CONFIG, config);
|
||||
|
||||
AccountDetailsFragment fragment = new AccountDetailsFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
final View v = inflater.inflate(R.layout.login_account_details, container, false);
|
||||
|
||||
Button btnBack = (Button)v.findViewById(R.id.back);
|
||||
btnBack.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
getFragmentManager().popBackStack();
|
||||
}
|
||||
});
|
||||
|
||||
final EditText editName = (EditText)v.findViewById(R.id.account_name);
|
||||
Button btnCreate = (Button)v.findViewById(R.id.create_account);
|
||||
btnCreate.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
String name = editName.getText().toString();
|
||||
if (name.isEmpty())
|
||||
editName.setError(getString(R.string.login_account_name_required));
|
||||
else {
|
||||
if (createAccount(name, (DavResourceFinder.Configuration)getArguments().getSerializable(KEY_CONFIG)))
|
||||
getActivity().finish();
|
||||
else
|
||||
Snackbar.make(v, R.string.login_account_not_created, Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
protected boolean createAccount(String accountName, DavResourceFinder.Configuration config) {
|
||||
Account account = new Account(accountName, Constants.ACCOUNT_TYPE);
|
||||
|
||||
Constants.log.info("Creating account {}, initial config: {}", accountName, config);
|
||||
|
||||
// create Android account
|
||||
AccountManager accountManager = AccountManager.get(getContext());
|
||||
Bundle userData = AccountSettings.initialUserData(config.userName, config.preemptive);
|
||||
if (!accountManager.addAccountExplicitly(account, config.password, userData))
|
||||
return false;
|
||||
|
||||
// add entries for account to service DB
|
||||
@Cleanup OpenHelper dbHelper = new OpenHelper(getContext());
|
||||
SQLiteDatabase db = dbHelper.getWritableDatabase();
|
||||
db.beginTransactionNonExclusive();
|
||||
try {
|
||||
if (config.cardDAV != null)
|
||||
insertService(db, accountName, Services.SERVICE_CARDDAV, config.cardDAV);
|
||||
|
||||
if (config.calDAV != null)
|
||||
insertService(db, accountName, Services.SERVICE_CALDAV, config.calDAV);
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void insertService(SQLiteDatabase db, String accountName, String service, DavResourceFinder.Configuration.ServiceInfo info) {
|
||||
ContentValues values = new ContentValues();
|
||||
|
||||
// insert service
|
||||
values.put(Services.ACCOUNT_NAME, accountName);
|
||||
values.put(Services.SERVICE, service);
|
||||
if (info.getPrincipal() != null)
|
||||
values.put(Services.PRINCIPAL, info.getPrincipal().toString());
|
||||
long serviceID = db.insertOrThrow(Services._TABLE, null, values);
|
||||
|
||||
// insert home sets
|
||||
for (HttpUrl homeSet : info.getHomeSets()) {
|
||||
values.clear();
|
||||
values.put(HomeSets.SERVICE_ID, serviceID);
|
||||
values.put(HomeSets.URL, homeSet.toString());
|
||||
db.insertOrThrow(HomeSets._TABLE, null, values);
|
||||
}
|
||||
|
||||
// insert collections
|
||||
for (Map.Entry<HttpUrl, DavResourceFinder.Configuration.Collection> entry : info.getCollections().entrySet()) {
|
||||
values = Collections.fromCollection(entry.getValue());
|
||||
values.put(Collections.SERVICE_ID, serviceID);
|
||||
values.put(Collections.URL, entry.getKey().toString());
|
||||
db.insertOrThrow(Collections._TABLE, null, values);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -11,11 +11,14 @@ package at.bitfire.davdroid.ui.setup;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@ -25,6 +28,7 @@ import at.bitfire.davdroid.Constants;
|
||||
import at.bitfire.davdroid.R;
|
||||
import at.bitfire.davdroid.resource.DavResourceFinder;
|
||||
import at.bitfire.davdroid.resource.DavResourceFinder.Configuration;
|
||||
import at.bitfire.davdroid.ui.DebugInfoActivity;
|
||||
import lombok.Cleanup;
|
||||
|
||||
public class DetectConfigurationFragment extends DialogFragment implements LoaderManager.LoaderCallbacks<Configuration> {
|
||||
@ -57,8 +61,18 @@ public class DetectConfigurationFragment extends DialogFragment implements Loade
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Configuration> loader, Configuration data) {
|
||||
// show error / continue with next fragment
|
||||
Constants.log.info("detection results: {}", data);
|
||||
if (data.calDAV == null && data.cardDAV == null)
|
||||
// no service found: show error message
|
||||
getFragmentManager().beginTransaction()
|
||||
.add(NothingDetectedFragment.newInstance(data.logs), null)
|
||||
.commitAllowingStateLoss();
|
||||
else
|
||||
// service found: continue
|
||||
getFragmentManager().beginTransaction()
|
||||
.replace(R.id.fragment, AccountDetailsFragment.newInstance(data))
|
||||
.addToBackStack(null)
|
||||
.commitAllowingStateLoss();
|
||||
|
||||
dismissAllowingStateLoss();
|
||||
}
|
||||
|
||||
@ -67,6 +81,41 @@ public class DetectConfigurationFragment extends DialogFragment implements Loade
|
||||
}
|
||||
|
||||
|
||||
public static class NothingDetectedFragment extends DialogFragment {
|
||||
private static String KEY_LOGS = "logs";
|
||||
|
||||
public static NothingDetectedFragment newInstance(String logs) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(KEY_LOGS, logs);
|
||||
NothingDetectedFragment fragment = new NothingDetectedFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.login_configuration_detection)
|
||||
.setIcon(R.drawable.ic_error_dark)
|
||||
.setMessage(R.string.login_no_caldav_carddav)
|
||||
.setNeutralButton(R.string.login_view_logs, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent(getActivity(), DebugInfoActivity.class);
|
||||
intent.putExtra(DebugInfoActivity.KEY_LOGS, getArguments().getString(KEY_LOGS));
|
||||
startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// dismiss
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
static class ServerConfigurationLoader extends AsyncTaskLoader<Configuration> {
|
||||
final Context context;
|
||||
final LoginCredentialsFragment.LoginCredentials credentials;
|
||||
|
@ -8,9 +8,13 @@
|
||||
|
||||
package at.bitfire.davdroid.ui.setup;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import at.bitfire.davdroid.Constants;
|
||||
import at.bitfire.davdroid.R;
|
||||
|
||||
public class LoginActivity extends AppCompatActivity {
|
||||
@ -28,4 +32,13 @@ public class LoginActivity extends AppCompatActivity {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.activity_login, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void showHelp(MenuItem item) {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("configuration/").build()));
|
||||
}
|
||||
}
|
||||
|
18
app/src/main/res/drawable/ic_error_dark.xml
Normal file
18
app/src/main/res/drawable/ic_error_dark.xml
Normal file
@ -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="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm1,15h-2v-2h2v2zm0,-4h-2V7h2v6z"/>
|
||||
</vector>
|
17
app/src/main/res/drawable/ic_help_light.xml
Normal file
17
app/src/main/res/drawable/ic_help_light.xml
Normal file
@ -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="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>
|
13
app/src/main/res/drawable/ic_share_light.xml
Normal file
13
app/src/main/res/drawable/ic_share_light.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
~ 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 android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFFFF" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
|
||||
</vector>
|
@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<fragment
|
||||
class="at.bitfire.davdroid.ui.AccountListFragment"
|
||||
android:id="@+id/account_list"
|
||||
android:layout_width="@dimen/leftcol_width"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
@ -7,39 +7,34 @@
|
||||
~ http://www.gnu.org/licenses/gpl.html
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:src="@drawable/gletschersee"
|
||||
android:scaleType="centerCrop"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentTop="true" />
|
||||
|
||||
<ListView
|
||||
android:id="@id/android:list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="@android:color/transparent" />
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="@android:color/transparent"
|
||||
android:background="@android:color/transparent"
|
||||
android:cacheColorHint="@android:color/transparent"/>
|
||||
|
||||
<RelativeLayout
|
||||
<TextView
|
||||
android:id="@id/android:empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="72dp"
|
||||
android:layout_marginRight="64dp"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/white"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large"
|
||||
android:text="@string/account_list_empty" />
|
||||
|
||||
<ImageView
|
||||
android:src="@drawable/gletschersee"
|
||||
android:scaleType="centerCrop"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentTop="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@id/android:empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="72dp"
|
||||
android:layout_marginRight="64dp"
|
||||
android:gravity="right|bottom"
|
||||
android:textColor="@color/white"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large"
|
||||
android:text="@string/account_list_empty" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
@ -1,25 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:clickable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
card_view:contentPadding="16dp"
|
||||
card_view:cardBackgroundColor="#ececec"
|
||||
card_view:cardElevation="2dp">
|
||||
style="@style/account_list_card"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
card_view:contentPadding="16dp"
|
||||
card_view:cardBackgroundColor="#ececec"
|
||||
card_view:cardElevation="2dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/carddav"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CardDAV"/>
|
||||
<TextView
|
||||
android:id="@+id/caldav"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="CalDAV"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/account_name"
|
||||
@ -27,7 +39,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
tools:text="Account Name"/>
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
@ -16,6 +16,15 @@
|
||||
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"
|
||||
@ -29,8 +38,6 @@
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay"/>
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_accounts"/>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
@ -18,7 +18,7 @@
|
||||
tools:openDrawer="start">
|
||||
|
||||
<include
|
||||
layout="@layout/app_bar_accounts"
|
||||
layout="@layout/accounts_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<fragment
|
||||
class="at.bitfire.davdroid.ui.AccountListFragment"
|
||||
android:id="@+id/account_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
75
app/src/main/res/layout/login_account_details.xml
Normal file
75
app/src/main/res/layout/login_account_details.xml
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="@dimen/activity_vertical_margin"
|
||||
android:layout_marginBottom="@dimen/activity_vertical_margin"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/login_type_headline"
|
||||
android:text="@string/login_create_account"
|
||||
android:layout_marginBottom="14dp"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/account_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/login_account_name"
|
||||
android:inputType="textEmailAddress"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/login_account_name_info"/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/stepper_nav_bar">
|
||||
|
||||
<Button
|
||||
android:id="@+id/back"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/login_back"
|
||||
style="@style/stepper_nav_button"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/create_account"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/login_create_account"
|
||||
style="@style/stepper_nav_button"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -41,6 +41,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/login_type_email"
|
||||
android:paddingLeft="14dp"
|
||||
style="@style/login_type_headline"/>
|
||||
|
||||
<LinearLayout
|
||||
@ -68,6 +69,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/login_type_url"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingLeft="14dp"
|
||||
style="@style/login_type_headline"/>
|
||||
|
||||
<LinearLayout
|
||||
@ -87,7 +89,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/login_user_name"
|
||||
android:inputType="textNoSuggestions"/>
|
||||
android:inputType="textEmailAddress"/>
|
||||
<at.bitfire.davdroid.ui.EditPassword
|
||||
android:id="@+id/url_password"
|
||||
android:layout_width="match_parent"
|
||||
@ -120,7 +122,7 @@
|
||||
android:id="@+id/login"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:text="Login"
|
||||
android:text="@string/login_login"
|
||||
style="@style/stepper_nav_button"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -7,12 +7,13 @@
|
||||
~ http://www.gnu.org/licenses/gpl.html
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:icon="@android:drawable/ic_menu_share"
|
||||
android:icon="@drawable/ic_share_light"
|
||||
android:title="@string/send"
|
||||
android:showAsAction="always"
|
||||
android:onClick="onShare" />
|
||||
app:showAsAction="always"
|
||||
android:onClick="onShare"/>
|
||||
|
||||
</menu>
|
@ -7,12 +7,15 @@
|
||||
~ http://www.gnu.org/licenses/gpl.html
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/help"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/help" android:onClick="showHelp">
|
||||
android:title="@string/help"
|
||||
android:icon="@drawable/ic_help_light"
|
||||
app:showAsAction="always"
|
||||
android:onClick="showHelp">
|
||||
</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/add_account"
|
||||
android:icon="@drawable/navigation_accept"
|
||||
android:showAsAction="always|withText"
|
||||
android:title="@string/setup_add_account">
|
||||
</item>
|
||||
|
||||
</menu>
|
18
app/src/main/res/values-w800dp/styles.xml
Normal file
18
app/src/main/res/values-w800dp/styles.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- AddAccountActivity -->
|
||||
|
||||
<style name="account_list_card">
|
||||
<item name="android:layout_width">600dp</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@ -12,7 +12,6 @@
|
||||
<!-- common strings -->
|
||||
<string name="app_name">DAVdroid</string>
|
||||
<string name="help">Help</string>
|
||||
<string name="next">Next</string>
|
||||
<string name="please_wait">Please wait</string>
|
||||
<string name="send">Send</string>
|
||||
<string name="skip">Skip</string>
|
||||
@ -104,9 +103,18 @@
|
||||
<string name="login_user_name_required">User name required</string>
|
||||
<string name="login_base_url">Base URL</string>
|
||||
<string name="login_auth_preemptive">Preemptive authentication (recommended, but incompatible with Digest auth)</string>
|
||||
<string name="login_login">Login</string>
|
||||
<string name="login_back">Back</string>
|
||||
<string name="login_create_account">Create account</string>
|
||||
<string name="login_account_name">Account name</string>
|
||||
<string name="login_account_name_info">Use your email address as account name because Android will use the account name as ORGANIZER field for events you create. You can\'t have two accounts with the same name.</string>
|
||||
<string name="login_account_name_required">Account name required</string>
|
||||
<string name="login_account_not_created">Account could not be created</string>
|
||||
|
||||
<string name="login_configuration_detection">Configuration detection</string>
|
||||
<string name="login_querying_server">Please wait, querying server…</string>
|
||||
<string name="login_no_caldav_carddav">Couldn\'t find CalDAV or CardDAV service.</string>
|
||||
<string name="login_view_logs">View logs</string>
|
||||
|
||||
<!-- Settings activity -->
|
||||
<string name="settings_title">Settings</string>
|
||||
@ -190,7 +198,6 @@
|
||||
<string name="setup_account_details">Account details</string>
|
||||
<string name="setup_account_name">Account name:</string>
|
||||
<string name="setup_account_name_hint">My CalDAV/CardDAV Account</string>
|
||||
<string name="setup_account_name_info">Use your email address as account name because Android will use the account name as ORGANIZER field for events you create. You can\'t have two accounts with the same name.</string>
|
||||
<string name="setup_read_only">read-only</string>
|
||||
|
||||
<!-- sync errors and DebugInfoActivity -->
|
||||
|
@ -38,8 +38,10 @@
|
||||
<!-- AddAccountActivity -->
|
||||
|
||||
<style name="login_type_headline">
|
||||
<item name="android:paddingLeft">14dp</item>
|
||||
<item name="android:textSize">20dp</item>
|
||||
<item name="android:textSize">22dp</item>
|
||||
</style>
|
||||
<style name="account_list_card">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
</style>
|
||||
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 94a5ee4aec98a29fe1c56046f9a6c71131db8b51
|
||||
Subproject commit 40aef8e2d5219c7595229a225c497c0e7237ec1c
|
Loading…
Reference in New Issue
Block a user