...
 
Commits (77)
......@@ -160,9 +160,9 @@ android {
setProperty("archivesBaseName", "$buildConfig.versionName-$versionCode")
generatedDensities = ["mdpi", "hdpi", "xhdpi"]
// testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testApplicationId "com.fsck.k9.pEp.ui.activities.test"
testInstrumentationRunner "com.fsck.k9.pEp.ui.activities.runner.CucumberTestRunner"
// testInstrumentationRunner "com.fsck.k9.pEp.ui.activities.runner.CucumberTestRunner"
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
......
package com.fsck.k9.matchers
import android.graphics.drawable.ColorDrawable
import android.view.View
import androidx.annotation.ColorRes
import androidx.core.content.res.ResourcesCompat
import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.TypeSafeMatcher
class BackgroundColourMatcher(@field:ColorRes @param:ColorRes private val mExpectedColourResId: Int) :
TypeSafeMatcher<View>(View::class.java) {
private var mColorFromView = 0
override fun matchesSafely(item: View): Boolean {
if (item.background == null) {
return false
}
val resources = item.context.resources
val colourFromResources = ResourcesCompat.getColor(resources, mExpectedColourResId, null)
mColorFromView = (item.background as ColorDrawable).color
return mColorFromView == colourFromResources
}
override fun describeTo(description: Description) {
description.appendText("Color did not match $mExpectedColourResId was $mColorFromView")
}
}
fun withBackgroundColour(@ColorRes expectedColor: Int): Matcher<View> {
return BackgroundColourMatcher(expectedColor)
}
\ No newline at end of file
......@@ -1240,7 +1240,7 @@ public class TestUtils {
while (!viewIsDisplayed(R.id.pEpTitle)) {
device.waitForIdle();
}
waitForTooblar();
waitForToolbar();
onView(withId(R.id.pEpTitle)).check(matches(withText(getResourceString(R.array.pep_title, status))));
if (!exists(onView(withId(R.id.send)))) {
goBack(false);
......@@ -1364,7 +1364,7 @@ public class TestUtils {
onView(withId(R.id.toolbar_container)).check(matches(isCompletelyDisplayed()));
device.waitForIdle();
waitUntilIdle();
waitForTooblar();
waitForToolbar();
onView(withId(R.id.toolbar)).check(matches(withBackgroundColor(color)));
checkUpperToolbar(color);
return;
......@@ -1391,7 +1391,7 @@ public class TestUtils {
device.waitForIdle();
}
public void waitForTooblar () {
public void waitForToolbar() {
for (int waitLoop = 0; waitLoop < 1000; waitLoop++) {
device.waitForIdle();
while (!viewIsDisplayed(R.id.toolbar) || !viewIsDisplayed(R.id.toolbar_container)) {
......
......@@ -1248,7 +1248,7 @@ public class CucumberTestSteps {
@Then("^I check if the privacy status is (\\S+)$")
public void I_check_toolBar_color_is(String color) {
timeRequiredForThisMethod(10);
testUtils.waitForTooblar();
testUtils.waitForToolbar();
boolean wait = false;
while (!wait) {
try {
......
package com.fsck.k9.pEp.ui.toolbar
import androidx.test.espresso.Espresso
import androidx.test.espresso.assertion.ViewAssertions
import androidx.core.content.ContextCompat
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import com.fsck.k9.R
import com.fsck.k9.activity.MessageList
import com.fsck.k9.activity.MessageCompose
import com.fsck.k9.matchers.withBackgroundColour
import com.fsck.k9.pEp.ui.activities.UtilsPackage
import com.fsck.k9.pEp.ui.activities.UtilsPackage.waitUntilIdle
import foundation.pEp.jniadapter.Rating
import org.hamcrest.Matchers.allOf
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import security.pEp.ui.PEpUIUtils
@RunWith(AndroidJUnit4::class)
class ToolBarCustomizerTest {
@get:Rule
var mActivityRule = ActivityTestRule(MessageList::class.java)
var mActivityRule = ActivityTestRule(MessageCompose::class.java)
@Test
fun check_if_status_bar_changes_color_by_color_resource() {
mActivityRule.activity.toolBarCustomizer.setStatusBarPepColor(R.color.white)
val colorRes = R.color.white
mActivityRule.activity.setStatusBarPepColor(colorRes)
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
val beforeColour = mActivityRule.activity.window.statusBarColor
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
mActivityRule.activity.toolBarCustomizer.setStatusBarPepColor(R.color.colorPrimary)
mActivityRule.activity.setStatusBarPepColor(colorRes)
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
Espresso.onView(withId(android.R.id.statusBarBackground))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
onView(withId(android.R.id.statusBarBackground))
.check(matches(ViewMatchers.isDisplayed()))
val afterColour = mActivityRule.activity.window.statusBarColor
......@@ -42,21 +51,68 @@ class ToolBarCustomizerTest {
@Test
fun check_if_status_bar_changes_color_by_rating() {
mActivityRule.activity.toolBarCustomizer.setStatusBarPepColor(Rating.pEpRatingReliable)
val rating = Rating.pEpRatingReliable
mActivityRule.activity.setStatusBarPepColor(rating)
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
val beforeColour = mActivityRule.activity.window.statusBarColor
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
mActivityRule.activity.toolBarCustomizer.setStatusBarPepColor(Rating.pEpRatingReliable)
mActivityRule.activity.setStatusBarPepColor(rating)
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
Espresso.onView(withId(android.R.id.statusBarBackground))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
onView(withId(android.R.id.statusBarBackground))
.check(matches(ViewMatchers.isDisplayed()))
val afterColour = mActivityRule.activity.window.statusBarColor
Assert.assertEquals(beforeColour, afterColour)
}
@Test
fun check_if_toolbar_changes_color_by_color_resource() {
waitForToolbar(50)
val colorRes = R.color.purple
val color = ContextCompat.getColor(mActivityRule.activity, colorRes)
mActivityRule.activity.setToolbarColor(color)
waitForToolbar(70)
if (isToolbarVisible())
onView(allOf(withId(R.id.toolbar))).check(matches(withBackgroundColour(colorRes)))
}
@Test
fun check_if_toolbar_changes_color_by_rating() {
waitForToolbar(50)
val rating = Rating.pEpRatingTrusted
val ratingColorRes = PEpUIUtils.getRatingColorRes(rating)
mActivityRule.activity.setToolbarColor(rating)
waitForToolbar(70)
if (isToolbarVisible())
onView(allOf(withId(R.id.toolbar))).check(matches(withBackgroundColour(ratingColorRes)))
}
private fun waitForToolbar(i: Int) {
for (waitLoop in 0..i) {
waitUntilIdle()
onView(withId(R.id.toolbar_container)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.toolbar)).check(matches(isCompletelyDisplayed()))
waitUntilIdle()
}
}
private fun isToolbarVisible(): Boolean {
return UtilsPackage.exists(onView(withId(R.id.toolbar)))
&& UtilsPackage.viewIsDisplayed(R.id.toolbar)
&& UtilsPackage.viewIsDisplayed(R.id.toolbar_container)
}
}
\ No newline at end of file
/*package com.fsck.k9.provider;
package com.fsck.k9.provider;
import android.database.Cursor;
import android.net.Uri;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.rule.provider.ProviderTestRule;
import androidx.test.runner.AndroidJUnit4;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static junit.framework.TestCase.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@RunWith(AndroidJUnit4.class)
public class MessageProviderTest extends ProviderTestCase2 {
public class MessageProviderTest {
private MockContentResolver mMockResolver;
private Cursor cursor;
public MessageProviderTest() {
super(MessageProvider.class, MessageProvider.AUTHORITY);
}
@Before
@Override
public void setUp() throws Exception {
super.setUp();
mMockResolver = getMockContentResolver();
mContext = K9.app;
Preferences preferences = Preferences.getPreferences(getMockContext());
List<Account> accountList = preferences.getAccounts();
for (Account account: accountList) {
preferences.deleteAccount(account);
}
}
@After
@Override
public void tearDown() throws Exception {
if (cursor != null) {
cursor.close();
}
super.tearDown();
}
@Rule
public ProviderTestRule mProviderRule =
new ProviderTestRule
.Builder(MessageProvider.class, MessageProvider.AUTHORITY)
.build();
private void createAccount() {
Preferences preferences = Preferences.getPreferences(getMockContext());
Preferences preferences = Preferences.getPreferences(ApplicationProvider.getApplicationContext());
Account account = preferences.newAccount();
account.setDescription("TestAccount");
account.setChipColor(10);
......@@ -63,9 +41,11 @@ public class MessageProviderTest extends ProviderTestCase2 {
@Test
public void query_forAccounts_withNoAccounts_returnsEmptyCursor() {
cursor = mMockResolver.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/accounts/"),
null, null, null, null);
cursor = mProviderRule
.getResolver()
.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/accounts/"),
null, null, null, null);
boolean isNotEmpty = cursor.moveToFirst();
......@@ -75,9 +55,11 @@ public class MessageProviderTest extends ProviderTestCase2 {
@Test
public void query_forAccounts_withAccount_returnsCursorWithData() {
createAccount();
cursor = mMockResolver.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/accounts/"),
null, null, null, null);
cursor = mProviderRule
.getResolver()
.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/accounts/"),
null, null, null, null);
boolean isNotEmpty = cursor.moveToFirst();
......@@ -88,24 +70,28 @@ public class MessageProviderTest extends ProviderTestCase2 {
public void query_forAccounts_withAccount_withNoProjection_returnsNumberAndName() {
createAccount();
cursor = mMockResolver.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/accounts/"),
null, null, null, null);
cursor = mProviderRule
.getResolver()
.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/accounts/"),
null, null, null, null);
cursor.moveToFirst();
assertEquals(2, cursor.getColumnCount());
assertEquals(0, cursor.getColumnIndex(MessageProvider.AccountColumns.ACCOUNT_NUMBER));
assertEquals(1, cursor.getColumnIndex(MessageProvider.AccountColumns.ACCOUNT_NAME));
assertEquals(0, cursor.getInt(0));
assertEquals("TestAccount", cursor.getString(1));
assertEquals("android09@peptest.ch", cursor.getString(1));
}
@Test
public void query_forInboxMessages_whenEmpty_returnsEmptyCursor() {
cursor = mMockResolver.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/inbox_messages/"),
null, null, null, null);
cursor = mProviderRule
.getResolver()
.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/inbox_messages/"),
null, null, null, null);
boolean isNotEmpty = cursor.moveToFirst();
......@@ -114,9 +100,11 @@ public class MessageProviderTest extends ProviderTestCase2 {
@Test
public void query_forAccountUnreadMessages_whenNoAccount_returnsEmptyCursor() {
cursor = mMockResolver.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/account_unread/0"),
null, null, null, null);
cursor = mProviderRule
.getResolver()
.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/account_unread/0"),
null, null, null, null);
boolean isNotEmpty = cursor.moveToFirst();
......@@ -126,15 +114,17 @@ public class MessageProviderTest extends ProviderTestCase2 {
@Test
public void query_forAccountUnreadMessages_whenNoMessages_returns0Unread() {
createAccount();
cursor = mMockResolver.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/account_unread/0"),
null, null, null, null);
cursor = mProviderRule
.getResolver()
.query(
Uri.parse("content://" + MessageProvider.AUTHORITY + "/account_unread/0"),
null, null, null, null);
cursor.moveToFirst();
assertEquals(2, cursor.getColumnCount());
assertEquals(1, cursor.getColumnIndex(MessageProvider.UnreadColumns.ACCOUNT_NAME));
assertEquals(0, cursor.getColumnIndex(MessageProvider.UnreadColumns.UNREAD));
assertEquals(0, cursor.getInt(0));
assertEquals("TestAccount", cursor.getString(1));
assertEquals("android09@peptest.ch", cursor.getString(1));
}
}*/
}
......@@ -1866,6 +1866,7 @@ public class K9 extends MultiDexApplication {
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(K9.this, R.string.pep_device_group, Toast.LENGTH_LONG).show());
break;
case SyncNotifySole:
needsFastPoll = false;
grouped = false;
break;
case SyncNotifyInGroup:
......
......@@ -9,6 +9,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils.TruncateAt;
import android.text.TextWatcher;
import android.text.format.DateUtils;
......@@ -21,6 +22,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
......@@ -336,8 +338,13 @@ public class FolderList extends K9ListActivity {
searchInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (searchInput!= null && !searchInput.getText().toString().isEmpty()) {
search(searchInput.getText().toString());
if (actionId == EditorInfo.IME_ACTION_SEARCH || (event != null && event.getAction() == KeyEvent.ACTION_DOWN)) {
if (searchInput != null && !searchInput.getText().toString().isEmpty()) {
search(searchInput.getText().toString());
}
else {
searchInput.setError(getString(R.string.search_empty_error));
}
}
return true;
}
......@@ -346,9 +353,7 @@ public class FolderList extends K9ListActivity {
clearSearchIcon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
searchInput.setText(null);
hideSearchView();
KeyboardUtils.hideKeyboard(searchInput);
}
});
}
......@@ -369,15 +374,20 @@ public class FolderList extends K9ListActivity {
if (searchLayout != null) {
getToolbar().setVisibility(View.GONE);
searchLayout.setVisibility(View.VISIBLE);
searchInput.setEnabled(true);
setFocusOnKeyboard();
searchInput.setError(null);
}
}
}
public void hideSearchView() {
if (searchLayout != null) {
getToolbar().setVisibility(View.VISIBLE);
searchLayout.setVisibility(View.GONE);
getToolbar().setVisibility(View.VISIBLE);
searchInput.setEnabled(false);
searchInput.setText(null);
KeyboardUtils.hideKeyboard(searchInput);
}
}
......@@ -448,7 +458,7 @@ public class FolderList extends K9ListActivity {
*/
@Override public void onResume() {
super.onResume();
hideSearchView();
if (!mAccount.isAvailable(this)) {
Timber.i("account unavaliabale, not showing folder-list but account-list");
SettingsActivity.Companion.listAccounts(this);
......@@ -463,7 +473,6 @@ public class FolderList extends K9ListActivity {
MessagingController.getInstance(getApplication()).addListener(mAdapter.mListener);
//mAccount.refresh(Preferences.getPreferences(this));
MessagingController.getInstance(getApplication()).getAccountStats(this, mAccount, mAdapter.mListener);
onRefresh(!REFRESH_REMOTE);
MessagingController.getInstance(getApplication()).cancelNotificationsForAccount(mAccount);
......@@ -474,37 +483,37 @@ public class FolderList extends K9ListActivity {
public boolean onKeyDown(int keyCode, KeyEvent event) {
//Shortcuts that work no matter what is selected
switch (keyCode) {
case KeyEvent.KEYCODE_Q: {
onAccounts();
return true;
}
case KeyEvent.KEYCODE_Q: {
onAccounts();
return true;
}
case KeyEvent.KEYCODE_S: {
onEditSettings();
return true;
}
case KeyEvent.KEYCODE_S: {
onEditSettings();
return true;
}
case KeyEvent.KEYCODE_H: {
FeedbackTools.showLongFeedback(getListView(), getString(R.string.folder_list_help_key));
return true;
}
case KeyEvent.KEYCODE_H: {
FeedbackTools.showLongFeedback(getListView(), getString(R.string.folder_list_help_key));
return true;
}
case KeyEvent.KEYCODE_1: {
setDisplayMode(FolderMode.FIRST_CLASS);
return true;
}
case KeyEvent.KEYCODE_2: {
setDisplayMode(FolderMode.FIRST_AND_SECOND_CLASS);
return true;
}
case KeyEvent.KEYCODE_3: {
setDisplayMode(FolderMode.NOT_SECOND_CLASS);
return true;
}
case KeyEvent.KEYCODE_4: {
setDisplayMode(FolderMode.ALL);
return true;
}
case KeyEvent.KEYCODE_1: {
setDisplayMode(FolderMode.FIRST_CLASS);
return true;
}
case KeyEvent.KEYCODE_2: {
setDisplayMode(FolderMode.FIRST_AND_SECOND_CLASS);
return true;
}
case KeyEvent.KEYCODE_3: {
setDisplayMode(FolderMode.NOT_SECOND_CLASS);
return true;
}
case KeyEvent.KEYCODE_4: {
setDisplayMode(FolderMode.ALL);
return true;
}
}//switch
......@@ -533,8 +542,7 @@ public class FolderList extends K9ListActivity {
}
private void onAccounts() {
SettingsActivity.Companion.listAccounts(this);
finish();
SettingsActivity.launch(this);
}
private void onEmptyTrash(final Account account) {
......@@ -678,12 +686,17 @@ public class FolderList extends K9ListActivity {
}
});
folderSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
folderMenuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem menuItem) {
menu.findItem(R.id.search).setVisible(false);
return true;
}
@Override
public boolean onClose() {
public boolean onMenuItemActionCollapse(MenuItem menuItem) {
getToolbar().setTitle(R.string.folders_title);
return false;
return true;
}
});
}
......@@ -1292,4 +1305,14 @@ public class FolderList extends K9ListActivity {
MessageList.actionDisplaySearch(FolderList.this, search, true, false, true);
}
}
@Override
public void onBackPressed() {
if(searchLayout != null && searchLayout.getVisibility() == View.VISIBLE) {
hideSearchView();
}
else {
super.onBackPressed();
}
}
}
package com.fsck.k9.activity;
import android.app.SearchManager;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
......@@ -40,6 +41,8 @@ public abstract class K9Activity extends AppCompatActivity implements K9Activity
private K9ActivityCommon mBase;
private View.OnClickListener onCloseSearchClickListener;
private boolean isAndroidLollipop = Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP ||
Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1;
@Override
public void onCreate(Bundle savedInstanceState) {
......@@ -93,16 +96,6 @@ public abstract class K9Activity extends AppCompatActivity implements K9Activity
this.onCloseSearchClickListener = onCloseSearchClickListener;
}
@Nullable @OnClick(R.id.search_clear)
void onClearSeachClicked() {
hideSearchView();
if (onCloseSearchClickListener != null) {
onCloseSearchClickListener.onClick(null);
}
searchInput.setText(null);
KeyboardUtils.hideKeyboard(searchInput);
}
public Toolbar getToolbar() {
return toolbar;
}
......@@ -128,31 +121,56 @@ public abstract class K9Activity extends AppCompatActivity implements K9Activity
return (ViewGroup) ((ViewGroup) this.findViewById(android.R.id.content)).getChildAt(0);
}
public boolean isAndroidLollipop() {
return isAndroidLollipop;
}
protected void showComposeFab(boolean showornot) {
findViewById(R.id.fab_button_compose_message).setVisibility(showornot? View.VISIBLE : View.GONE);
}
public void showSearchView() {
if(Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP ||
Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1) {
if (isAndroidLollipop) {
onSearchRequested();
showComposeFab(false);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchManager.setOnDismissListener(() -> showComposeFab(true));
} else {
if (toolbarSearchContainer != null && toolbar != null) {
if (toolbarSearchContainer != null && toolbar != null
&& searchInput != null) {
toolbarSearchContainer.setVisibility(View.VISIBLE);
toolbar.setVisibility(View.GONE);
searchInput.setEnabled(true);
setFocusOnKeyboard();
searchInput.setError(null);
showComposeFab(false);
}
}
}
private void setFocusOnKeyboard() {
if (searchInput != null) {
searchInput.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(searchInput, InputMethodManager.SHOW_IMPLICIT);
}
searchInput.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(searchInput, InputMethodManager.SHOW_IMPLICIT);
}
protected boolean isSearchViewVisible() {
return toolbarSearchContainer != null && toolbarSearchContainer.getVisibility() == View.VISIBLE;
}
@Nullable @OnClick(R.id.search_clear)
public void hideSearchView() {
if (toolbarSearchContainer != null && toolbar != null) {
if (searchInput != null &&
toolbarSearchContainer != null && toolbar != null) {
toolbarSearchContainer.setVisibility(View.GONE);
toolbar.setVisibility(View.VISIBLE);
searchInput.setEnabled(false);
searchInput.setText(null);
KeyboardUtils.hideKeyboard(searchInput);
if (onCloseSearchClickListener != null) {
onCloseSearchClickListener.onClick(null);
}
showComposeFab(true);
}
}
......@@ -170,24 +188,20 @@ public abstract class K9Activity extends AppCompatActivity implements K9Activity
@Nullable @OnEditorAction(R.id.search_input)
boolean onSearchInputSubmitted(KeyEvent keyEvent) {
if (searchInput != null) {
String searchedText = searchInput.getText().toString();
if (!searchedText.trim().isEmpty()) {
search(searchInput.getText().toString());
return true;
if (keyEvent != null && keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
String searchedText = searchInput.getText().toString();
if (!searchedText.trim().isEmpty()) {
search(searchInput.getText().toString());
return true;
}
else {
searchInput.setError(getString(R.string.search_empty_error));
}
}
}
return false;
}
@Nullable @OnClick(R.id.search_clear)
public void onClearText() {
if (searchInput != null) {
searchInput.setText(null);
hideSearchView();
KeyboardUtils.hideKeyboard(searchInput);
}
}
public void bindViews(@LayoutRes int layoutId) {
setContentView(layoutId);
ButterKnife.bind(this);
......
......@@ -3,9 +3,6 @@ package com.fsck.k9.activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
......@@ -13,6 +10,11 @@ import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.activity.K9ActivityCommon.K9ActivityMagic;
......@@ -116,6 +118,13 @@ public abstract class K9ListActivity extends AppCompatActivity implements K9Acti
}
}
public void initializeToolbar(Boolean showUpButton, @StringRes int stringResource) {
setUpToolbar(showUpButton);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayShowTitleEnabled(true);
getSupportActionBar().setTitle(getResources().getString(stringResource));
}
}
public Toolbar getToolbar() {
return toolbar;
}
......
......@@ -353,11 +353,10 @@ class SettingsActivity : PEpImporterActivity(), PreferenceFragmentCompat.OnPrefe
accounts.clear()
accounts.addAll(Preferences.getPreferences(this).accounts)
// see if we should show the welcome message
// if (accounts.length < 1) {
// WelcomeMessage.showWelcomeMessage(this);
// finish();
// }
if (accounts.size < 1) {
AccountSetupBasics.actionNewAccount(this)
finishAffinity()
}
val newAccounts: MutableList<BaseAccount>
if (!K9.isHideSpecialAccounts() && accounts.size > 0) {
......
......@@ -51,7 +51,7 @@ public class UnreadWidgetConfiguration extends AccountList {
return;
}
setTitle(R.string.unread_widget_select_account);
initializeToolbar(false, R.string.unread_widget_select_account);
}
@Override
......
package com.fsck.k9.activity.compose;
import java.util.Arrays;
import java.util.List;
import android.app.PendingIntent;
import androidx.loader.app.LoaderManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
......@@ -19,6 +15,8 @@ import android.view.View.OnFocusChangeListener;
import android.widget.TextView;
import android.widget.ViewAnimator;
import androidx.loader.app.LoaderManager;
import com.fsck.k9.Account;
import com.fsck.k9.FontSizes;
import com.fsck.k9.R;
......@@ -31,16 +29,17 @@ import com.fsck.k9.pEp.PEpUtils;
import com.fsck.k9.pEp.PePUIArtefactCache;
import com.fsck.k9.pEp.ui.ActionRecipientSelectView;
import com.fsck.k9.pEp.ui.privacy.status.PEpStatus;
import com.fsck.k9.pEp.ui.privacy.status.PEpTrustwords;
import com.fsck.k9.pEp.ui.tools.FeedbackTools;
import com.fsck.k9.view.RecipientSelectView.Recipient;
import com.fsck.k9.view.RecipientSelectView.TokenListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import foundation.pEp.jniadapter.Identity;
import foundation.pEp.jniadapter.Rating;
import java.util.ArrayList;
public class RecipientMvpView implements OnFocusChangeListener, OnClickListener {
private static final int VIEW_INDEX_HIDDEN = -1;
......@@ -492,30 +491,22 @@ public class RecipientMvpView implements OnFocusChangeListener, OnClickListener
public void setpEpRating(Rating pEpRating) {
this.pEpRating = pEpRating;
}
public Rating getpEpRating() {
return pEpRating;
}
public void handlepEpState(boolean... withToast) {
if (mAccount.ispEpPrivacyProtected()) {
boolean reallyWithToast = true;
if(withToast.length>0) reallyWithToast = withToast[0];
if (withToast.length > 0) reallyWithToast = withToast[0];
updatePePState();
activity.toolBarCustomizer.setToolbarColor(pEpUiCache.getColor(Rating.pEpRatingUndefined));
if(pEpIndicator!=null) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
pEpIndicator.setIcon(pEpUiCache.getIcon());
}
});
if (pEpIndicator != null) {
new Handler(Looper.getMainLooper()).post(() -> pEpIndicator.setIcon(pEpUiCache.getIcon()));
String msg = pEpUiCache.getTitle(pEpRating);
}
} else {
activity.toolBarCustomizer.setToolbarColor(pEpUiCache.getColor(Rating.pEpRatingUndefined));
}
activity.toolBarCustomizer.setStatusBarPepColor(pEpRating);
activity.setToolbarRating(pEpRating);
}
void updatePePState() {
......@@ -536,7 +527,7 @@ public class RecipientMvpView implements OnFocusChangeListener, OnClickListener
// mIgnoreOnPause = true; // do *not* save state
pEpUiCache.setRecipients(mAccount, recipients);
PEpStatus.actionShowStatus(activity, pEpRating, getFrom(), messageReference, false, getFrom());
PEpStatus.actionShowStatus(activity, pEpRating, getFrom(), messageReference, false, getFrom(), presenter.isForceUnencrypted());
}
public void setMessageReference(MessageReference reference) {
......
......@@ -321,8 +321,6 @@ public class RecipientPresenter {
menu.findItem(R.id.add_from_contacts).setVisible(false);
}
menu.findItem(R.id.pEp_indicator).setVisible(account.ispEpPrivacyProtected());
menu.findItem(R.id.force_unencrypted).setVisible(account.ispEpPrivacyProtected());
}
......@@ -874,9 +872,9 @@ public class RecipientPresenter {
}
private void loadPEpStatus() {
if (forceUnencrypted) {
showRatingFeedback(Rating.pEpRatingUnencrypted);
} else {
// if (forceUnencrypted) {
// showRatingFeedback(Rating.pEpRatingUnencrypted);
// } else {
Address fromAddress = recipientMvpView.getFromAddress();
List<Address> newToAdresses = recipientMvpView.getToAddresses();
List<Address> newCcAdresses = recipientMvpView.getCcAddresses();
......@@ -920,7 +918,7 @@ public class RecipientPresenter {
});
}
recipientMvpView.unlockSendButton();
}
// }
}
private void showDefaultStatus() {
......
......@@ -755,7 +755,9 @@ public class MessageListFragment extends PEpFragment implements ConfirmationDial
senderAboveSubject = K9.messageListSenderAboveSubject();
if (!loaderJustInitialized) {
restartLoader();
if(accountExists()) {
restartLoader();
}
} else {
loaderJustInitialized = false;
}
......@@ -790,7 +792,7 @@ public class MessageListFragment extends PEpFragment implements ConfirmationDial
updateTitle();
MessageList activity = (MessageList) getActivity();
if (!activity.isMessageViewVisible() && activity.isThreadDisplayed()) {
toolBarCustomizer.setToolbarColor(PEpUtils.getRatingColor(worstThreadRating, getActivity()));
toolBarCustomizer.setToolbarColor(worstThreadRating);
toolBarCustomizer.setStatusBarPepColor(worstThreadRating);
}
if (isThreadDisplay) {
......@@ -800,6 +802,10 @@ public class MessageListFragment extends PEpFragment implements ConfirmationDial
}
}
private boolean accountExists() {
return preferences.getAccounts().contains(account);
}
private void restartLoader() {
if (cursorValid == null) {
return;
......@@ -2987,7 +2993,7 @@ public class MessageListFragment extends PEpFragment implements ConfirmationDial
cursor.moveToNext();
}
if (!((MessageList) getActivity()).isMessageViewVisible()) {
toolBarCustomizer.setToolbarColor(PEpUtils.getRatingColor(worstThreadRating, getActivity()));
toolBarCustomizer.setToolbarColor(worstThreadRating);
toolBarCustomizer.setStatusBarPepColor(worstThreadRating);
}
}
......
......@@ -2,40 +2,22 @@
package com.fsck.k9.mailstore;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import timber.log.Timber;
import androidx.annotation.Nullable;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.activity.MessageReference;
import com.fsck.k9.controller.PendingCommandSerializer;
import com.fsck.k9.controller.MessagingControllerCommands.PendingCommand;
import com.fsck.k9.controller.PendingCommandSerializer;
import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.Body;
import com.fsck.k9.mail.BodyPart;
......@@ -65,12 +47,34 @@ import com.fsck.k9.search.LocalSearch;
import com.fsck.k9.search.SearchSpecification.Attribute;
import com.fsck.k9.search.SearchSpecification.SearchField;
import com.fsck.k9.search.SqlQueryBuilder;
import org.apache.commons.io.IOUtils;
import org.apache.james.mime4j.codec.Base64InputStream;
import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
import org.apache.james.mime4j.util.MimeUtil;
import org.openintents.openpgp.util.OpenPgpApi.OpenPgpDataSource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import timber.log.Timber;
/**
* <pre>
* Implements a SQLite database backed local store for Messages.
......@@ -587,7 +591,7 @@ public class LocalStore extends Store implements Serializable {
String[] selectionArgs = queryArgs.toArray(new String[queryArgs.size()]);
String sqlQuery = "SELECT " + GET_MESSAGES_COLS + "FRO M messages " +
String sqlQuery = "SELECT " + GET_MESSAGES_COLS + "FROM messages " +
"LEFT JOIN threads ON (threads.message_id = messages.id) " +
"LEFT JOIN message_parts ON (message_parts.id = messages.message_part_id) " +
"LEFT JOIN folders ON (folders.id = messages.folder_id) WHERE " +
......
......@@ -167,7 +167,6 @@ public class PEpUtils {
return adr;
}
// /**
// * dumps a k9 msg to log
// *
......@@ -331,32 +330,6 @@ public class PEpUtils {
}
public static int getRatingColor(Rating rating, Context context) {
// TODO: 02/09/16 PEP_color color_from_rating(PEP_rating rating) from pEpEngine;
if (rating == null || rating.equals(Rating.pEpRatingB0rken)
|| rating.equals(Rating.pEpRatingHaveNoKey)) {
return ContextCompat.getColor(context, R.color.pep_no_color);
}
if (rating.value < Rating.pEpRatingUndefined.value) {
return ContextCompat.getColor(context, R.color.pep_red);
}
if (rating.value < Rating.pEpRatingReliable.value) {
return ContextCompat.getColor(context, R.color.pep_no_color);
}
if (rating.value < Rating.pEpRatingTrusted.value) {
return ContextCompat.getColor(context, R.color.pep_yellow);
}
if (rating.value >= Rating.pEpRatingTrusted.value) {
return ContextCompat.getColor(context, R.color.pep_green);
}
throw new RuntimeException("Invalid rating");
}
public static Rating extractRating(Message message) {
String[] pEpRating;
pEpRating = message.getHeader(MimeHeader.HEADER_PEP_RATING);
......@@ -385,7 +358,6 @@ public class PEpUtils {
return String.valueOf(fprChars);
}
public static boolean ispEpDisabled(Account account, Rating messageRating) {
return messageRating == Rating.pEpRatingUndefined
|| !account.ispEpPrivacyProtected();
......@@ -409,29 +381,6 @@ public class PEpUtils {
}
}
public static void colorToolbar(PePUIArtefactCache uiCache, Toolbar toolbar, Rating pEpRating) {
if (toolbar != null) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
toolbar.setBackgroundColor(uiCache.getColor(pEpRating));
}
});
}
}
public static void colorToolbar(PePUIArtefactCache uiCache, ActionBar supportActionBar, Rating pEpRating) {
ColorDrawable colorDrawable = new ColorDrawable(uiCache.getColor(pEpRating));
supportActionBar.setBackgroundDrawable(colorDrawable);
}
public static void colorToolbar(Toolbar toolbar, int colorResource) {
if (toolbar != null) {
toolbar.setBackgroundColor(colorResource);
}
}
public static ArrayList<Identity> filterRecipients(Account account, ArrayList<Identity> recipients) {
ArrayList<Identity> identities = new ArrayList<>();
......@@ -482,34 +431,6 @@ public class PEpUtils {
return rt;
}
public static Drawable getDrawableForRating(Context context, Rating rating) {
if (rating.value != Rating.pEpRatingMistrust.value
&& rating.value < Rating.pEpRatingReliable.value) {
return context.getResources().getDrawable(R.drawable.pep_status_gray);
} else if (rating.value == Rating.pEpRatingMistrust.value) {
return context.getResources().getDrawable(R.drawable.pep_status_red);
} else if (rating.value >= Rating.pEpRatingTrusted.value) {
return context.getResources().getDrawable(R.drawable.pep_status_green);
} else if (rating.value == Rating.pEpRatingReliable.value) {
return context.getResources().getDrawable(R.drawable.pep_status_yellow);
}
return context.getResources().getDrawable(R.drawable.pep_status_gray);
}
public static Drawable getDrawableForRatingRecipient(Context context, Rating rating) {
if (rating.value != Rating.pEpRatingMistrust.value
&& rating.value < Rating.pEpRatingReliable.value) {
return context.getResources().getDrawable(R.drawable.pep_status_gray_white);
} else if (rating.value == Rating.pEpRatingMistrust.value) {
return context.getResources().getDrawable(R.drawable.pep_status_red_white);
} else if (rating.value >= Rating.pEpRatingTrusted.value) {
return context.getResources().getDrawable(R.drawable.pep_status_green_dark);
} else if (rating.value == Rating.pEpRatingReliable.value) {
return context.getResources().getDrawable(R.drawable.pep_status_yellow_white);
}
return context.getResources().getDrawable(R.drawable.pep_status_gray_white);
}
public static String addressesToString(Address[] addresses) {
String addressesText = "";
for (int i = 0; i < addresses.length; i++) {
......
......@@ -91,11 +91,6 @@ public class PePUIArtefactCache
return ContextCompat.getDrawable(context, R.drawable.ic_action_pep_indicator_white);
}
public int getColor(Rating pEpRating) {
return PEpUtils.getRatingColor(pEpRating, context);
}
public ArrayList<Identity> getRecipients() {
if (recipients == null) {
return new ArrayList<>();
......
......@@ -2,13 +2,23 @@ package com.fsck.k9.pEp.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import com.fsck.k9.view.RecipientSelectView;
import org.jetbrains.annotations.NotNull;
import security.pEp.ui.input.utils.InputConnectionProvider;
import security.pEp.ui.input.utils.InputConnectionProviderImpl;
public class ActionRecipientSelectView extends RecipientSelectView {
private InputConnectionProvider inputConnectionProvider;