diff --git a/app/build.gradle b/app/build.gradle index 68f49f7c..f1d627f3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,16 +55,20 @@ configurations.all { } dependencies { - compile 'dnsjava:dnsjava:2.1.7' - compile 'org.apache.commons:commons-lang3:3.4' provided 'org.projectlombok:lombok:1.16.6' - compile 'org.slf4j:slf4j-android:1.7.13' compile project(':dav4android') compile project(':ical4android') compile project(':vcard4android') + compile 'com.android.support:appcompat-v7:23.+' + compile 'com.android.support:cardview-v7:23.+' + compile 'com.android.support:design:23.+' + compile project(':MemorizingTrustManager') androidTestCompile 'com.squareup.okhttp:mockwebserver:2.7.2' + compile 'dnsjava:dnsjava:2.1.7' + compile 'org.apache.commons:commons-lang3:3.4' + compile 'org.slf4j:slf4j-android:1.7.13' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 37d7820e..e99a0f1d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,64 +5,75 @@ ~ 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 - --> - - +--> + - - - - + + + + - - - + + + - - - - - + + + + + + + - - + android:theme="@style/AppTheme" + tools:ignore="UnusedAttribute"> - + + + android:resource="@xml/account_authenticator"/> - - + + + android:resource="@xml/sync_contacts"/> + android:resource="@xml/contacts"/> - + + + android:resource="@xml/sync_calendars"/> - + + + android:resource="@xml/sync_tasks"/> + android:name=".ui.AccountsActivity" + android:label="@string/app_name" + android:theme="@style/AppTheme.NoActionBar"> - - + + + android:name=".ui.AddAccountActivity" + android:label="@string/login_title" + android:parentActivityName=".ui.AccountsActivity" + android:noHistory="true"> + + + + android:name=".ui.DebugInfoActivity" + android:exported="true" + android:label="@string/debug_info_title"> + android:label="@string/settings_title"> - - + + + + android:parentActivityName=".ui.settings.SettingsActivity" + tools:ignore="UnusedAttribute"> - + diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountAuthenticatorService.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountAuthenticatorService.java index c20ea722..4ca038f6 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountAuthenticatorService.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountAuthenticatorService.java @@ -18,7 +18,7 @@ import android.content.Intent; import android.os.Bundle; import android.os.IBinder; -import at.bitfire.davdroid.ui.setup.AddAccountActivity; +import at.bitfire.davdroid.ui.AddAccountActivity; public class AccountAuthenticatorService extends Service { private static AccountAuthenticator accountAuthenticator; diff --git a/app/src/main/java/at/bitfire/davdroid/ui/AccountListFragment.java b/app/src/main/java/at/bitfire/davdroid/ui/AccountListFragment.java new file mode 100644 index 00000000..d517240b --- /dev/null +++ b/app/src/main/java/at/bitfire/davdroid/ui/AccountListFragment.java @@ -0,0 +1,81 @@ +/* + * 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; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.OnAccountsUpdateListener; +import android.content.Context; +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import at.bitfire.davdroid.Constants; +import at.bitfire.davdroid.R; + +public class AccountListFragment extends ListFragment implements OnAccountsUpdateListener { + + protected AccountManager accountManager; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + setListAdapter(new AccountListAdapter(getContext())); + + accountManager = AccountManager.get(getContext()); + accountManager.addOnAccountsUpdatedListener(this, null, true); + + return inflater.inflate(R.layout.account_list, container, false); + } + + @Override + public void onDestroyView() { + accountManager.removeOnAccountsUpdatedListener(this); + super.onDestroyView(); + } + + @Override + public void onAccountsUpdated(Account[] accounts) { + AccountListAdapter adapter = (AccountListAdapter)getListAdapter(); + if (adapter != null) { + adapter.clear(); + for (Account account : accounts) + if (Constants.ACCOUNT_TYPE.equals(account.type)) + adapter.add(account); + } + } + + + class AccountListAdapter extends ArrayAdapter { + + public AccountListAdapter(Context context) { + super(context, R.layout.account_list_item); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View v = convertView; + + if (v == null) { + LayoutInflater inflater = LayoutInflater.from(getContext()); + v = inflater.inflate(R.layout.account_list_item, parent, false); + } + + Account account = getItem(position); + + TextView tvName = (TextView)v.findViewById(R.id.account_name); + tvName.setText(account.name); + + return v; + } + } +} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/AccountsActivity.java b/app/src/main/java/at/bitfire/davdroid/ui/AccountsActivity.java new file mode 100644 index 00000000..9656862c --- /dev/null +++ b/app/src/main/java/at/bitfire/davdroid/ui/AccountsActivity.java @@ -0,0 +1,82 @@ +/* + * 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; + +import android.content.Intent; +import android.os.Bundle; +import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.NavigationView; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.MenuItem; +import android.view.View; + +import at.bitfire.davdroid.Constants; +import at.bitfire.davdroid.R; + +public class AccountsActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_accounts); + + Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + startActivity(new Intent(AccountsActivity.this, AddAccountActivity.class)); + } + }); + + DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout); + ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( + this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); + drawer.setDrawerListener(toggle); + toggle.syncState(); + + NavigationView navigationView = (NavigationView)findViewById(R.id.nav_view); + navigationView.setNavigationItemSelectedListener(this); + } + + @Override + public void onBackPressed() { + DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout); + if (drawer.isDrawerOpen(GravityCompat.START)) + drawer.closeDrawer(GravityCompat.START); + else + super.onBackPressed(); + } + + @Override + public boolean onNavigationItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.nav_about: + break; + case R.id.nav_website: + startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri)); + break; + case R.id.nav_donate: + startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("donate/").build())); + break; + case R.id.nav_preferences: + break; + } + + DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout); + drawer.closeDrawer(GravityCompat.START); + return true; + } +} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/AddAccountActivity.java b/app/src/main/java/at/bitfire/davdroid/ui/AddAccountActivity.java new file mode 100644 index 00000000..b3c8fcc4 --- /dev/null +++ b/app/src/main/java/at/bitfire/davdroid/ui/AddAccountActivity.java @@ -0,0 +1,25 @@ +/* + * 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; + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; + +import at.bitfire.davdroid.R; + +public class AddAccountActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_add_account); + } + +} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/EditPassword.java b/app/src/main/java/at/bitfire/davdroid/ui/EditPassword.java new file mode 100644 index 00000000..419bd83c --- /dev/null +++ b/app/src/main/java/at/bitfire/davdroid/ui/EditPassword.java @@ -0,0 +1,45 @@ +/* + * 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; + +import android.content.Context; +import android.support.v7.widget.AppCompatCheckBox; +import android.util.AttributeSet; +import android.view.inputmethod.EditorInfo; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.LinearLayout; + +import at.bitfire.davdroid.R; + +public class EditPassword extends LinearLayout { + + public EditPassword(Context context) { + super(context, null); + } + + public EditPassword(Context context, AttributeSet attrs) { + super(context, attrs); + + inflate(context, R.layout.edit_password, this); + + final EditText editPassword = (EditText)findViewById(R.id.password); + + AppCompatCheckBox checkShowPassword = (AppCompatCheckBox)findViewById(R.id.show_password); + checkShowPassword.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + int inputType = editPassword.getInputType() & ~EditorInfo.TYPE_MASK_VARIATION; + inputType |= isChecked ? EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD : EditorInfo.TYPE_TEXT_VARIATION_PASSWORD; + editPassword.setInputType(inputType); + } + }); + } + +} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/MainActivity.java b/app/src/main/java/at/bitfire/davdroid/ui/MainActivity.java deleted file mode 100644 index 8e4b3395..00000000 --- a/app/src/main/java/at/bitfire/davdroid/ui/MainActivity.java +++ /dev/null @@ -1,134 +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.ui; - -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.provider.Settings; -import android.text.Html; -import android.text.method.LinkMovementMethod; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.TextView; - -import at.bitfire.davdroid.BuildConfig; -import at.bitfire.davdroid.Constants; -import at.bitfire.davdroid.R; -import at.bitfire.davdroid.ui.settings.SettingsActivity; -import at.bitfire.davdroid.ui.setup.AddAccountActivity; -import lombok.Getter; - -public class MainActivity extends Activity { - - private static final String libraries = - "· Apache CommonsApache License, Version 2.0
" + - "· dnsjavaBSD License
" + - "· ez-vcardNew BSD License
" + - "· iCal4jNew BSD License
" + - "· MemorizingTrustManagerMIT License
" + - "· okhttpApache License, Version 2.0
" + - "· Project LombokMIT License
" + - "· SLF4j (Simple Logging Facade for Java) – MIT License"; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.main_activity); - - TextView tv = (TextView)findViewById(R.id.text_store_specific); - final String installedFrom = installedFrom(); - if (installedFrom == null || installedFrom.startsWith("org.fdroid")) { - if (savedInstanceState == null) - new DonateDialogFragment().show(getFragmentManager(), "donate"); - } else if ("com.android.vending".equals(installedFrom)) - setHtmlText(R.id.text_store_specific, R.string.main_play_workaround_html); - - setPlainText(R.id.text_welcome, R.string.main_welcome, BuildConfig.VERSION_NAME); - setHtmlText(R.id.text_what_is_davdroid, R.string.main_what_is_davdroid_html); - setHtmlText(R.id.text_how_to_setup, R.string.main_how_to_setup_html); - setHtmlText(R.id.text_support, R.string.main_support_html); - setHtmlText(R.id.text_open_source_disclaimer, R.string.main_open_source_disclaimer_html); - setHtmlText(R.id.text_license, R.string.main_license_html); - setPlainText(R.id.text_libraries_heading, R.string.main_used_libraries_heading); - setHtmlText(R.id.text_libraries_list, libraries); - } - - private void setPlainText(int viewId, int stringId, Object... args) { - TextView tv = (TextView)findViewById(viewId); - tv.setVisibility(View.VISIBLE); - tv.setText(getString(stringId, args)); - } - - private void setHtmlText(int viewId, int stringId, Object... args) { - TextView tv = (TextView)findViewById(viewId); - tv.setVisibility(View.VISIBLE); - tv.setText(trim(Html.fromHtml(getString(stringId, args)))); - tv.setMovementMethod(LinkMovementMethod.getInstance()); - } - - private void setHtmlText(int viewId, String html) { - TextView tv = (TextView)findViewById(viewId); - tv.setVisibility(View.VISIBLE); - tv.setText(trim(Html.fromHtml(html))); - tv.setMovementMethod(LinkMovementMethod.getInstance()); - } - - private CharSequence trim(CharSequence text) { - while (text.charAt(text.length() - 1) == '\n') { - text = text.subSequence(0, text.length() - 1); - } - return text; - } - - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.main_activity, menu); - return true; - } - - - public void addAccount(MenuItem item) { - startActivity(new Intent(this, AddAccountActivity.class)); - } - - public void showDebugInfo(MenuItem item) { - startActivity(new Intent(this, DebugInfoActivity.class)); - } - - public void showSettings(MenuItem item) { - startActivity(new Intent(this, SettingsActivity.class)); - } - - public void showSyncSettings(MenuItem item) { - Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS); - startActivity(intent); - } - - public void showWebsite(MenuItem item) { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Constants.webUri); - startActivity(intent); - } - - - private String installedFrom() { - try { - return getPackageManager().getInstallerPackageName("at.bitfire.davdroid"); - } catch(IllegalArgumentException e) { - return null; - } - } -} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.java b/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.java deleted file mode 100644 index 3d7a678f..00000000 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.java +++ /dev/null @@ -1,193 +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.ui.setup; - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.app.Fragment; -import android.content.ContentProviderClient; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.os.Bundle; -import android.provider.CalendarContract; -import android.provider.ContactsContract; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.EditText; -import android.widget.TextView; -import android.widget.Toast; - -import at.bitfire.davdroid.Constants; -import at.bitfire.davdroid.R; -import at.bitfire.davdroid.resource.LocalAddressBook; -import at.bitfire.davdroid.resource.LocalCalendar; -import at.bitfire.davdroid.resource.LocalTaskList; -import at.bitfire.davdroid.resource.ServerInfo; -import at.bitfire.davdroid.syncadapter.AccountSettings; -import at.bitfire.ical4android.CalendarStorageException; -import at.bitfire.ical4android.TaskProvider; -import at.bitfire.vcard4android.ContactsStorageException; -import lombok.Cleanup; - -public class AccountDetailsFragment extends Fragment implements TextWatcher { - public static final String TAG = "davdroid.AccountDetails"; - - ServerInfo serverInfo; - - EditText editAccountName; - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.setup_account_details, container, false); - - serverInfo = ((AddAccountActivity)getActivity()).serverInfo; - - editAccountName = (EditText)v.findViewById(R.id.account_name); - editAccountName.addTextChangedListener(this); - editAccountName.setText(serverInfo.getUserName()); - - TextView textAccountNameInfo = (TextView)v.findViewById(R.id.account_name_info); - if (!serverInfo.hasEnabledCalendars()) - textAccountNameInfo.setVisibility(View.GONE); - - setHasOptionsMenu(true); - return v; - } - - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.setup_account_details, menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.add_account: - addAccount(); - break; - default: - return false; - } - return true; - } - - - // actions - - @SuppressWarnings("Recycle") - void addAccount() { - String accountName = editAccountName.getText().toString(); - - AccountManager accountManager = AccountManager.get(getActivity()); - Account account = new Account(accountName, Constants.ACCOUNT_TYPE); - Bundle userData = AccountSettings.createBundle(serverInfo); - - if (accountManager.addAccountExplicitly(account, serverInfo.getPassword(), userData)) { - addSync(account, ContactsContract.AUTHORITY, serverInfo.getAddressBooks(), new AddSyncCallback() { - @Override - public void createLocalCollection(Account account, ServerInfo.ResourceInfo resource) throws ContactsStorageException { - @Cleanup("release") ContentProviderClient provider = getActivity().getContentResolver().acquireContentProviderClient(ContactsContract.AUTHORITY); - if (provider != null) { - LocalAddressBook addressBook = new LocalAddressBook(account, provider); - - // set URL - addressBook.setURL(resource.getUrl()); - - // set Settings - ContentValues settings = new ContentValues(2); - settings.put(ContactsContract.Settings.SHOULD_SYNC, 1); - settings.put(ContactsContract.Settings.UNGROUPED_VISIBLE, 1); - addressBook.updateSettings(settings); - } else - Constants.log.error("Couldn't access Contacts Provider"); - } - }); - - addSync(account, CalendarContract.AUTHORITY, serverInfo.getCalendars(), new AddSyncCallback() { - @Override - public void createLocalCollection(Account account, ServerInfo.ResourceInfo calendar) { - try { - LocalCalendar.create(account, getActivity().getContentResolver(), calendar); - } catch(CalendarStorageException e) { - Constants.log.error("Couldn't create local calendar", e); - } - } - }); - - addSync(account, TaskProvider.ProviderName.OpenTasks.authority, serverInfo.getTaskLists(), new AddSyncCallback() { - @Override - public void createLocalCollection(Account account, ServerInfo.ResourceInfo todoList) { - try { - LocalTaskList.create(account, getActivity().getContentResolver(), todoList); - } catch (CalendarStorageException e) { - Constants.log.error("Couldn't create local task list", e); - } - } - }); - - getActivity().finish(); - } else - Toast.makeText(getActivity(), "Couldn't create account (account with this name already existing?)", Toast.LENGTH_LONG).show(); - } - - protected interface AddSyncCallback { - void createLocalCollection(Account account, ServerInfo.ResourceInfo resource) throws ContactsStorageException; - } - - protected void addSync(Account account, String authority, ServerInfo.ResourceInfo[] resourceList, AddSyncCallback callback) { - boolean sync = false; - for (ServerInfo.ResourceInfo resource : resourceList) - if (resource.isEnabled()) { - sync = true; - if (callback != null) - try { - callback.createLocalCollection(account, resource); - } catch(ContactsStorageException e) { - Log.e(TAG, "Couldn't add sync collection", e); - Toast.makeText(getActivity(), "Couldn't set up synchronization for " + authority, Toast.LENGTH_LONG).show(); - } - } - if (sync) { - ContentResolver.setIsSyncable(account, authority, 1); - ContentResolver.setSyncAutomatically(account, authority, true); - } else - ContentResolver.setIsSyncable(account, authority, 0); - } - - - // input validation - - @Override - public void onPrepareOptionsMenu(Menu menu) { - boolean ok = editAccountName.getText().length() > 0; - MenuItem item = menu.findItem(R.id.add_account); - item.setEnabled(ok); - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - getActivity().invalidateOptionsMenu(); - } - - @Override - public void afterTextChanged(Editable s) { - } -} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/AddAccountActivity.java b/app/src/main/java/at/bitfire/davdroid/ui/setup/AddAccountActivity.java deleted file mode 100644 index 23934f9a..00000000 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/AddAccountActivity.java +++ /dev/null @@ -1,60 +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.ui.setup; - -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; - -import at.bitfire.davdroid.Constants; -import at.bitfire.davdroid.R; -import at.bitfire.davdroid.resource.ServerInfo; - -public class AddAccountActivity extends Activity { - final private static String KEY_SERVER_INFO = "serverInfo"; - - protected ServerInfo serverInfo; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (savedInstanceState != null) - serverInfo = (ServerInfo)savedInstanceState.getSerializable(KEY_SERVER_INFO); - - setContentView(R.layout.setup_add_account); - - if (savedInstanceState == null) { // first call - getFragmentManager().beginTransaction() - .add(R.id.right_pane, new LoginTypeFragment()) - .commit(); - } - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putSerializable(KEY_SERVER_INFO, serverInfo); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.setup_add_account, menu); - return true; - } - - public void showHelp(MenuItem item) { - startActivityForResult(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("configuration/").build()), 0); - } - -} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/InstallAppsFragment.java b/app/src/main/java/at/bitfire/davdroid/ui/setup/InstallAppsFragment.java deleted file mode 100644 index 423fc353..00000000 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/InstallAppsFragment.java +++ /dev/null @@ -1,63 +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.ui.setup; - -import android.app.Fragment; -import android.os.Bundle; -import android.text.Html; -import android.text.method.LinkMovementMethod; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import at.bitfire.davdroid.R; - -public class InstallAppsFragment extends Fragment { - // https://code.google.com/p/android/issues/detail?id=25906 - - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.setup_install_apps, container, false); - setHasOptionsMenu(true); - - TextView tvInfo = (TextView)v.findViewById(R.id.setup_install_tasks_app); - tvInfo.setText(Html.fromHtml(getString(R.string.setup_install_tasks_app_html))); - tvInfo.setMovementMethod(LinkMovementMethod.getInstance()); - - return v; - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.only_skip, menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.skip: - skip(); - break; - default: - return false; - } - return true; - } - - protected void skip() { - getFragmentManager().beginTransaction() - .replace(R.id.right_pane, new SelectCollectionsFragment()) - .addToBackStack(null) - .commit(); - } - -} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginEmailFragment.java b/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginEmailFragment.java deleted file mode 100644 index da3e0621..00000000 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginEmailFragment.java +++ /dev/null @@ -1,130 +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.ui.setup; - -import android.app.DialogFragment; -import android.app.Fragment; -import android.content.Context; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; - -import java.net.URI; -import java.net.URISyntaxException; - -import at.bitfire.davdroid.Constants; -import at.bitfire.davdroid.R; -import at.bitfire.davdroid.resource.ServerInfo; - -public class LoginEmailFragment extends Fragment implements TextWatcher { - - protected EditText editEmail, editPassword; - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.setup_login_email, container, false); - - editEmail = (EditText)v.findViewById(R.id.email_address); - editEmail.addTextChangedListener(this); - - editPassword = (EditText)v.findViewById(R.id.password); - editPassword.addTextChangedListener(this); - - setHasOptionsMenu(true); - return v; - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.only_next, menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.next: - try { - String email = editEmail.getText().toString(); - Bundle args = new Bundle(); - args.putSerializable(QueryServerDialogFragment.KEY_SERVER_INFO, new ServerInfo( - new URI("mailto:" + email), - email, - editPassword.getText().toString(), - true - )); - - DialogFragment dialog = new QueryServerDialogFragment(); - dialog.setArguments(args); - dialog.show(getFragmentManager(), QueryServerDialogFragment.class.getName()); - } catch (URISyntaxException e) { - Constants.log.debug("Invalid email address", e); - } - break; - default: - return false; - } - return true; - } - - @Override - public void onResume() { - super.onResume(); - // set focus and show soft keyboard - if (editEmail.requestFocus()) { - InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(editEmail, InputMethodManager.SHOW_IMPLICIT); - } - } - - - // input validation - - @Override - public void onPrepareOptionsMenu(Menu menu) { - boolean emailOk = false, - passwordOk = editPassword.getText().length() > 0; - - String email = editEmail.getText().toString(); - try { - URI uri = new URI("mailto:" + email); - if (uri.isOpaque()) { - int pos = email.lastIndexOf("@"); - if (pos != -1) - emailOk = !email.substring(pos + 1).isEmpty(); - } - } catch (URISyntaxException e) { - // invalid mailto: URI - } - - MenuItem item = menu.findItem(R.id.next); - item.setEnabled(emailOk && passwordOk); - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - getActivity().invalidateOptionsMenu(); - } - - @Override - public void afterTextChanged(Editable s) { - } - -} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginTypeFragment.java b/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginTypeFragment.java deleted file mode 100644 index 0945321b..00000000 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginTypeFragment.java +++ /dev/null @@ -1,57 +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.ui.setup; - -import android.app.Fragment; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.RadioButton; - -import at.bitfire.davdroid.R; - -public class LoginTypeFragment extends Fragment { - - protected RadioButton btnTypeEmail; - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.setup_login_type, container, false); - - btnTypeEmail = (RadioButton)v.findViewById(R.id.login_type_email); - - setHasOptionsMenu(true); - - return v; - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.only_next, menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.next: - Fragment loginFragment = btnTypeEmail.isChecked() ? new LoginEmailFragment() : new LoginURLFragment(); - getFragmentManager().beginTransaction() - .replace(R.id.right_pane, loginFragment) - .addToBackStack(null) - .commitAllowingStateLoss(); - return true; - default: - return false; - } - } -} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginURLFragment.java b/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginURLFragment.java deleted file mode 100644 index 348a4513..00000000 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginURLFragment.java +++ /dev/null @@ -1,168 +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.ui.setup; - -import android.app.Activity; -import android.app.DialogFragment; -import android.app.Fragment; -import android.content.Context; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.CheckBox; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.TextView; - -import java.net.URI; -import java.net.URISyntaxException; - -import at.bitfire.davdroid.Constants; -import at.bitfire.davdroid.R; -import at.bitfire.davdroid.resource.ServerInfo; - -public class LoginURLFragment extends Fragment implements TextWatcher { - - protected Spinner spnrScheme; - protected TextView textHttpWarning; - protected EditText editBaseURI, editUserName, editPassword; - protected CheckBox checkboxPreemptive; - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.setup_login_url, container, false); - - // protocol selection spinner - textHttpWarning = (TextView)v.findViewById(R.id.http_warning); - - spnrScheme = (Spinner)v.findViewById(R.id.login_scheme); - spnrScheme.setOnItemSelectedListener(new OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - String scheme = parent.getAdapter().getItem(position).toString(); - textHttpWarning.setVisibility(scheme.equals("https://") ? View.GONE : View.VISIBLE); - } - - @Override - public void onNothingSelected(AdapterView parent) { - } - }); - spnrScheme.setSelection(1); // HTTPS - - // other input fields - editBaseURI = (EditText)v.findViewById(R.id.login_host_path); - editBaseURI.addTextChangedListener(this); - - editUserName = (EditText)v.findViewById(R.id.userName); - editUserName.addTextChangedListener(this); - - editPassword = (EditText)v.findViewById(R.id.password); - editPassword.addTextChangedListener(this); - - checkboxPreemptive = (CheckBox)v.findViewById(R.id.auth_preemptive); - - // hook into action bar - setHasOptionsMenu(true); - - return v; - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.only_next, menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.next: - try { - ServerInfo serverInfo = new ServerInfo( - getBaseURI(), - editUserName.getText().toString(), - editPassword.getText().toString(), - checkboxPreemptive.isChecked() - ); - Bundle args = new Bundle(); - args.putSerializable(QueryServerDialogFragment.KEY_SERVER_INFO, serverInfo); - DialogFragment dialog = new QueryServerDialogFragment(); - dialog.setArguments(args); - dialog.show(getFragmentManager(), null); - } catch (URISyntaxException e) { - Constants.log.debug("Invalid URI", e); - } - break; - default: - return false; - } - return true; - } - - @Override - public void onResume() { - super.onResume(); - // set focus and show soft keyboard - if (editBaseURI.requestFocus()) { - InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(editBaseURI, InputMethodManager.SHOW_IMPLICIT); - } - } - - - private URI getBaseURI() throws URISyntaxException { - String scheme = spnrScheme.getSelectedItem().toString(), - host_path = editBaseURI.getText().toString(); - return new URI(scheme + host_path); - } - - - // input validation - - @Override - public void onPrepareOptionsMenu(Menu menu) { - boolean usernameOk = editUserName.getText().length() > 0, - passwordOk = editPassword.getText().length() > 0, - urlOk = false; - - // check host name - try { - if (!TextUtils.isEmpty(getBaseURI().getHost())) - urlOk = true; - } catch (Exception e) { - } - - MenuItem item = menu.findItem(R.id.next); - item.setEnabled(usernameOk && passwordOk && urlOk); - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - Activity activity = getActivity(); - if (activity != null) - activity.invalidateOptionsMenu(); - } - - @Override - public void afterTextChanged(Editable s) { - } -} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/QueryServerDialogFragment.java b/app/src/main/java/at/bitfire/davdroid/ui/setup/QueryServerDialogFragment.java deleted file mode 100644 index 2c17207e..00000000 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/QueryServerDialogFragment.java +++ /dev/null @@ -1,184 +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.ui.setup; - -import android.annotation.SuppressLint; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.app.Fragment; -import android.app.LoaderManager.LoaderCallbacks; -import android.app.ProgressDialog; -import android.content.AsyncTaskLoader; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.Loader; -import android.os.Bundle; -import android.view.WindowManager; -import android.view.inputmethod.InputMethodManager; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; - -import at.bitfire.davdroid.Constants; -import at.bitfire.davdroid.R; -import at.bitfire.davdroid.log.StringLogger; -import at.bitfire.davdroid.resource.DavResourceFinder; -import at.bitfire.davdroid.resource.LocalTaskList; -import at.bitfire.davdroid.resource.ServerInfo; -import at.bitfire.davdroid.ui.DebugInfoActivity; -import lombok.Cleanup; - -public class QueryServerDialogFragment extends DialogFragment implements LoaderCallbacks { - public static final String KEY_SERVER_INFO = "server_info"; - - public static QueryServerDialogFragment newInstance(ServerInfo serverInfo) { - Bundle args = new Bundle(); - args.putSerializable(KEY_SERVER_INFO, serverInfo); - QueryServerDialogFragment fragment = new QueryServerDialogFragment(); - fragment.setArguments(args); - return fragment; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - ProgressDialog dialog = new ProgressDialog(getActivity()); - dialog.setCanceledOnTouchOutside(false); - setCancelable(false); - - dialog.setTitle(R.string.setup_resource_detection); - dialog.setIndeterminate(true); - dialog.setMessage(getString(R.string.setup_querying_server)); - return dialog; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Loader loader = getLoaderManager().initLoader(0, getArguments(), this); - } - - @Override - public Loader onCreateLoader(int id, Bundle args) { - return new ServerInfoLoader(getActivity(), args); - } - - @Override - @SuppressLint("CommitTransaction") - public void onLoadFinished(Loader loader, ServerInfo serverInfo) { - if (serverInfo.isEmpty()) { - // resource detection didn't find anything - getFragmentManager().beginTransaction() - .add(NothingDetectedFragment.newInstance(serverInfo.getLogs()), null) - .commitAllowingStateLoss(); - - } else { - ((AddAccountActivity)getActivity()).serverInfo = serverInfo; - - // resource detection brought some results - Fragment nextFragment; - if (serverInfo.getTaskLists().length > 0 && !LocalTaskList.tasksProviderAvailable(getActivity().getContentResolver())) - nextFragment = new InstallAppsFragment(); - else - nextFragment = new SelectCollectionsFragment(); - - getFragmentManager().beginTransaction() - .replace(R.id.right_pane, nextFragment) - .addToBackStack(null) - .commitAllowingStateLoss(); - } - - getDialog().dismiss(); - } - - @Override - public void onLoaderReset(Loader arg0) { - } - - - 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.setup_resource_detection) - .setIcon(android.R.drawable.ic_dialog_info) - .setMessage(R.string.setup_no_collections_found) - .setNeutralButton(R.string.setup_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 ServerInfoLoader extends AsyncTaskLoader { - private static final String TAG = "davdroid.ServerInfoLoader"; - final Bundle args; - final Context context; - - public ServerInfoLoader(Context context, Bundle args) { - super(context); - this.context = context; - this.args = args; - } - - @Override - protected void onStartLoading() { - forceLoad(); - } - - @Override - public ServerInfo loadInBackground() { - ServerInfo serverInfo = (ServerInfo)args.getSerializable(KEY_SERVER_INFO); - - StringLogger logger = new StringLogger("DavResourceFinder", true); - DavResourceFinder finder = new DavResourceFinder(logger, context, serverInfo); - finder.findResources(); - - // duplicate logs to ADB - String logs = logger.toString(); - try { - @Cleanup BufferedReader logStream = new BufferedReader(new StringReader(logs)); - Constants.log.info("Successful resource detection:"); - String line; - while ((line = logStream.readLine()) != null) - Constants.log.debug(line); - } catch (IOException e) { - Constants.log.error("Couldn't read resource detection logs", e); - } - - serverInfo.setLogs(logger.toString()); - - return serverInfo; - } - } - -} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/SelectCollectionsAdapter.java b/app/src/main/java/at/bitfire/davdroid/ui/setup/SelectCollectionsAdapter.java deleted file mode 100644 index 3187ed59..00000000 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/SelectCollectionsAdapter.java +++ /dev/null @@ -1,217 +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.ui.setup; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.CheckedTextView; -import android.widget.ListAdapter; - -import at.bitfire.davdroid.R; -import at.bitfire.davdroid.resource.LocalTaskList; -import at.bitfire.davdroid.resource.ServerInfo; -import lombok.Getter; - -/** - * Order of display: - * - * number of rows type - * nAddressBookHeadings (0 or 1) heading: "address books" - * nAddressBooks address book info - * nCalendarHeadings (0 or 1) heading: "calendars" - * nCalendars calendar info - * nNotebookHeadings (0 or 1) heading: "notebooks" - * nNotebooks notebook info - * nTaskListHeadings (0 or 1) heading: "task lists" - * nTaskLists task list info - */ -public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter { - final static int - TYPE_ADDRESS_BOOKS_HEADING = 0, - TYPE_ADDRESS_BOOKS_ROW = 1, - TYPE_CALENDARS_HEADING = 2, - TYPE_CALENDARS_ROW = 3, - TYPE_TASK_LISTS_HEADING = 4, - TYPE_TASK_LISTS_ROW = 5; - - final protected Context context; - final protected ServerInfo serverInfo; - @Getter protected int - nAddressBooks, nAddressBookHeadings, - nCalendars, nCalendarHeadings, - nTaskLists, nTaskListHeadings; - - - public SelectCollectionsAdapter(Context context, ServerInfo serverInfo) { - this.context = context; - - this.serverInfo = serverInfo; - nAddressBooks = serverInfo.getAddressBooks().length; - nAddressBookHeadings = nAddressBooks == 0 ? 0 : 1; - nCalendars = serverInfo.getCalendars().length; - nCalendarHeadings = nCalendars == 0 ? 0 : 1; - nTaskLists = serverInfo.getTaskLists().length; - nTaskListHeadings = nTaskLists == 0 ? 0 : 1; - } - - - // item data - - @Override - public int getCount() { - return nAddressBookHeadings + nAddressBooks + nCalendarHeadings + nCalendars + nTaskListHeadings + nTaskLists; - } - - @Override - public Object getItem(int position) { - if (position >= nAddressBookHeadings && - position < (nAddressBookHeadings + nAddressBooks)) - return serverInfo.getAddressBooks()[position - nAddressBookHeadings]; - - else if (position >= (nAddressBookHeadings + nAddressBooks + nCalendarHeadings) && - (position < (nAddressBookHeadings + nAddressBooks + nCalendarHeadings + nCalendars))) - return serverInfo.getCalendars()[position - (nAddressBookHeadings + nAddressBooks + nCalendarHeadings)]; - - else if (position >= (nAddressBookHeadings + nAddressBooks + nCalendarHeadings + nCalendars + nTaskListHeadings) && - (position < (nAddressBookHeadings + nAddressBooks + nCalendarHeadings + nCalendars + nTaskListHeadings + nTaskLists))) - return serverInfo.getTaskLists()[position - (nAddressBookHeadings + nAddressBooks + nCalendarHeadings + nCalendars + nTaskListHeadings)]; - - return null; - } - - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public long getItemId(int position) { - return position; - } - - - // item views - - @Override - public int getViewTypeCount() { - return TYPE_TASK_LISTS_ROW + 1; - } - - @Override - public int getItemViewType(int position) { - if ((nAddressBookHeadings != 0) && (position == 0)) - return TYPE_ADDRESS_BOOKS_HEADING; - else if ((nAddressBooks != 0) && (position > 0) && (position < nAddressBookHeadings + nAddressBooks)) - return TYPE_ADDRESS_BOOKS_ROW; - - else if ((nCalendarHeadings != 0) && (position == nAddressBookHeadings + nAddressBooks)) - return TYPE_CALENDARS_HEADING; - else if ((nCalendars != 0) && (position > nAddressBookHeadings + nAddressBooks) && (position < nAddressBookHeadings + nAddressBooks + nCalendarHeadings + nCalendars)) - return TYPE_CALENDARS_ROW; - - else if ((nTaskListHeadings != 0) && (position == nAddressBookHeadings + nAddressBooks + nCalendarHeadings + nCalendars)) - return TYPE_TASK_LISTS_HEADING; - else if ((nTaskLists != 0) && (position > nAddressBookHeadings + nAddressBooks + nCalendarHeadings + nCalendars) && (position < nAddressBookHeadings + nAddressBooks + nCalendarHeadings + nCalendars + nTaskListHeadings + nTaskLists)) - return TYPE_TASK_LISTS_ROW; - - else - return IGNORE_ITEM_VIEW_TYPE; - } - - @Override - @SuppressLint("InflateParams") - public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - - int viewType = getItemViewType(position); - - // step 1: get view (either by creating or recycling) - if (v == null) { - LayoutInflater inflater = LayoutInflater.from(parent.getContext()); - switch (viewType) { - case TYPE_ADDRESS_BOOKS_HEADING: - v = inflater.inflate(R.layout.setup_address_books_heading, parent, false); - break; - case TYPE_ADDRESS_BOOKS_ROW: - v = inflater.inflate(android.R.layout.simple_list_item_single_choice, null); - v.setPadding(0, 8, 0, 8); - break; - case TYPE_CALENDARS_HEADING: - v = inflater.inflate(R.layout.setup_calendars_heading, parent, false); - break; - case TYPE_TASK_LISTS_HEADING: - v = inflater.inflate(R.layout.setup_task_lists_heading, parent, false); - break; - case TYPE_CALENDARS_ROW: - case TYPE_TASK_LISTS_ROW: - v = inflater.inflate(android.R.layout.simple_list_item_multiple_choice, null); - v.setPadding(0, 8, 0, 8); - } - } - - // step 2: fill view with content - switch (viewType) { - case TYPE_ADDRESS_BOOKS_ROW: - setContent((CheckedTextView)v, R.drawable.addressbook, (ServerInfo.ResourceInfo)getItem(position)); - break; - case TYPE_CALENDARS_ROW: - setContent((CheckedTextView)v, R.drawable.calendar, (ServerInfo.ResourceInfo)getItem(position)); - break; - case TYPE_TASK_LISTS_ROW: - setContent((CheckedTextView)v, R.drawable.tasks, (ServerInfo.ResourceInfo)getItem(position)); - } - - // disable task list selection if there's no local task provider - if (viewType == TYPE_TASK_LISTS_ROW && !LocalTaskList.tasksProviderAvailable(context.getContentResolver())) { - final CheckedTextView check = (CheckedTextView)v; - check.setEnabled(false); - check.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - check.setChecked(false); - } - }); - } - - return v; - } - - protected void setContent(CheckedTextView view, int collectionIcon, ServerInfo.ResourceInfo info) { - // set layout and icons - view.setCompoundDrawablesWithIntrinsicBounds(collectionIcon, 0, info.isReadOnly() ? R.drawable.ic_read_only : 0, 0); - view.setCompoundDrawablePadding(10); - - // set text - String title = "" + info.getTitle() + ""; - if (info.isReadOnly()) - title = title + " (" + context.getString(R.string.setup_read_only) + ")"; - - String description = info.getDescription(); - if (description == null) - description = info.getUrl(); - - // FIXME escape HTML - view.setText(Html.fromHtml(title + "
" + description)); - } - - @Override - public boolean areAllItemsEnabled() { - return false; - } - - @Override - public boolean isEnabled(int position) { - int type = getItemViewType(position); - return (type == TYPE_ADDRESS_BOOKS_ROW || type == TYPE_CALENDARS_ROW || type == TYPE_TASK_LISTS_ROW); - } -} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/SelectCollectionsFragment.java b/app/src/main/java/at/bitfire/davdroid/ui/setup/SelectCollectionsFragment.java deleted file mode 100644 index 85a439cb..00000000 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/SelectCollectionsFragment.java +++ /dev/null @@ -1,125 +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.ui.setup; - -import android.app.ListFragment; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ListAdapter; -import android.widget.ListView; - -import at.bitfire.davdroid.R; -import at.bitfire.davdroid.resource.ServerInfo; - -public class SelectCollectionsFragment extends ListFragment { - - protected ServerInfo serverInfo; - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - serverInfo = ((AddAccountActivity)getActivity()).serverInfo; - - View v = super.onCreateView(inflater, container, savedInstanceState); - setHasOptionsMenu(true); - - return v; - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - setListAdapter(null); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - final ListView listView = getListView(); - listView.setPadding(20, 30, 20, 30); - - View header = getActivity().getLayoutInflater().inflate(R.layout.setup_select_collections_header, getListView(), false); - listView.addHeaderView(header, getListView(), false); - - final SelectCollectionsAdapter adapter = new SelectCollectionsAdapter(view.getContext(), serverInfo); - setListAdapter(adapter); - - listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); - listView.setOnItemClickListener(new OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - int itemPosition = position - 1; // one list header view at pos. 0 - if (adapter.getItemViewType(itemPosition) == SelectCollectionsAdapter.TYPE_ADDRESS_BOOKS_ROW) { - // unselect all other address books - for (int pos = 1; pos <= adapter.getNAddressBooks(); pos++) - if (pos != itemPosition) - listView.setItemChecked(pos + 1, false); - } - - getActivity().invalidateOptionsMenu(); - } - }); - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.only_next, menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.next: - // synchronize only selected collections - for (ServerInfo.ResourceInfo addressBook : serverInfo.getAddressBooks()) - addressBook.setEnabled(false); - for (ServerInfo.ResourceInfo calendar : serverInfo.getCalendars()) - calendar.setEnabled(false); - for (ServerInfo.ResourceInfo todoList : serverInfo.getTaskLists()) - todoList.setEnabled(false); - - ListAdapter adapter = getListView().getAdapter(); - for (long id : getListView().getCheckedItemIds()) { - int position = (int)id + 1; // +1 because header view is inserted at pos. 0 - ServerInfo.ResourceInfo info = (ServerInfo.ResourceInfo)adapter.getItem(position); - info.setEnabled(true); - } - - getFragmentManager().beginTransaction() - .replace(R.id.right_pane, new AccountDetailsFragment()) - .addToBackStack(null) - .commitAllowingStateLoss(); - break; - default: - return false; - } - return true; - } - - - // input validation - - @Override - public void onPrepareOptionsMenu(Menu menu) { - boolean ok = false; - try { - ok = getListView().getCheckedItemCount() > 0; - } catch (IllegalStateException e) { - } - MenuItem item = menu.findItem(R.id.next); - item.setEnabled(ok); - } -} diff --git a/app/src/main/res/color/buttontext.xml b/app/src/main/res/color/buttontext.xml new file mode 100644 index 00000000..1ec931b0 --- /dev/null +++ b/app/src/main/res/color/buttontext.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-nodpi/gletschersee.jpg b/app/src/main/res/drawable-nodpi/gletschersee.jpg new file mode 100644 index 00000000..04e9aaf3 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/gletschersee.jpg differ diff --git a/app/src/main/res/drawable/ic_add_light.xml b/app/src/main/res/drawable/ic_add_light.xml new file mode 100644 index 00000000..c9fd7462 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_light.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_attach_money_dark.xml b/app/src/main/res/drawable/ic_attach_money_dark.xml new file mode 100644 index 00000000..9db797f0 --- /dev/null +++ b/app/src/main/res/drawable/ic_attach_money_dark.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_home_dark.xml b/app/src/main/res/drawable/ic_home_dark.xml new file mode 100644 index 00000000..2452758f --- /dev/null +++ b/app/src/main/res/drawable/ic_home_dark.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_info_dark.xml b/app/src/main/res/drawable/ic_info_dark.xml new file mode 100644 index 00000000..814d75df --- /dev/null +++ b/app/src/main/res/drawable/ic_info_dark.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_settings_dark.xml b/app/src/main/res/drawable/ic_settings_dark.xml new file mode 100644 index 00000000..a270cf87 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings_dark.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_visibility_dark.xml b/app/src/main/res/drawable/ic_visibility_dark.xml new file mode 100644 index 00000000..def11add --- /dev/null +++ b/app/src/main/res/drawable/ic_visibility_dark.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_visibility_off_dark.xml b/app/src/main/res/drawable/ic_visibility_off_dark.xml new file mode 100644 index 00000000..a73d6154 --- /dev/null +++ b/app/src/main/res/drawable/ic_visibility_off_dark.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/password_eye_button.xml b/app/src/main/res/drawable/password_eye_button.xml new file mode 100644 index 00000000..24e23ca7 --- /dev/null +++ b/app/src/main/res/drawable/password_eye_button.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/side_nav_bar.xml b/app/src/main/res/drawable/side_nav_bar.xml new file mode 100644 index 00000000..e99a6188 --- /dev/null +++ b/app/src/main/res/drawable/side_nav_bar.xml @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-large/content_accounts.xml b/app/src/main/res/layout-large/content_accounts.xml new file mode 100644 index 00000000..10290a32 --- /dev/null +++ b/app/src/main/res/layout-large/content_accounts.xml @@ -0,0 +1,23 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-sw720dp/settings_activity.xml b/app/src/main/res/layout-sw720dp/settings_activity.xml index d1f63173..092203f6 100644 --- a/app/src/main/res/layout-sw720dp/settings_activity.xml +++ b/app/src/main/res/layout-sw720dp/settings_activity.xml @@ -14,7 +14,7 @@ android:layout_height="match_parent"> diff --git a/app/src/main/res/layout/account_list.xml b/app/src/main/res/layout/account_list.xml new file mode 100644 index 00000000..c31d6015 --- /dev/null +++ b/app/src/main/res/layout/account_list.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/account_list_item.xml b/app/src/main/res/layout/account_list_item.xml new file mode 100644 index 00000000..24f58c9e --- /dev/null +++ b/app/src/main/res/layout/account_list_item.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_accounts.xml b/app/src/main/res/layout/activity_accounts.xml new file mode 100644 index 00000000..1c0d86ad --- /dev/null +++ b/app/src/main/res/layout/activity_accounts.xml @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_add_account.xml b/app/src/main/res/layout/activity_add_account.xml new file mode 100644 index 00000000..1faf72a1 --- /dev/null +++ b/app/src/main/res/layout/activity_add_account.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +