Skip to content

Commit 4f13b4d

Browse files
committed
use ChatsFragment instead of FindFragment when sharing to Tinode
1 parent 0c273fb commit 4f13b4d

File tree

6 files changed

+215
-18
lines changed

6 files changed

+215
-18
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
android:supportsRtl="true"
6363
android:allowBackup="false"
6464
android:requestLegacyExternalStorage="true"
65-
tools:ignore="AllowBackup"
65+
tools:ignore="AllowBackup,DataExtractionRules"
6666
tools:targetApi="q">
6767

6868
<meta-data

app/src/main/java/co/tinode/tindroid/ChatsAdapter.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.content.Context;
55
import android.content.res.TypedArray;
66
import android.graphics.Typeface;
7+
import android.text.TextUtils;
78
import android.view.LayoutInflater;
89
import android.view.MotionEvent;
910
import android.view.View;
@@ -15,6 +16,7 @@
1516
import java.util.Collection;
1617
import java.util.HashMap;
1718
import java.util.List;
19+
import java.util.Locale;
1820

1921
import androidx.annotation.NonNull;
2022
import androidx.annotation.Nullable;
@@ -30,6 +32,7 @@
3032
import co.tinode.tinodesdk.ComTopic;
3133
import co.tinode.tinodesdk.Storage;
3234
import co.tinode.tinodesdk.model.Drafty;
35+
import co.tinode.tinodesdk.model.TheCard;
3336

3437
/**
3538
* Handling active chats, i.e. 'me' topic.
@@ -44,14 +47,17 @@ public class ChatsAdapter extends RecyclerView.Adapter<ChatsAdapter.ViewHolder>
4447
private HashMap<String, Integer> mTopicIndex;
4548
private SelectionTracker<String> mSelectionTracker;
4649
private final Filter mTopicFilter;
50+
// Optional filter to find topics by name.
51+
private Filter mTextFilter = null;
4752

48-
ChatsAdapter(Context context, ClickListener clickListener, Filter filter) {
53+
ChatsAdapter(Context context, ClickListener clickListener, @Nullable Filter filter) {
4954
super();
5055

5156
mClickListener = clickListener;
52-
mTopicFilter = filter;
57+
mTopicFilter = filter != null ? filter : topic -> true;
5358

5459
setHasStableIds(true);
60+
setTextFilter(null);
5561

5662
sColorOffline = ResourcesCompat.getColor(context.getResources(),
5763
R.color.offline, context.getTheme());
@@ -65,7 +71,9 @@ void resetContent(Activity activity) {
6571
}
6672

6773
final Collection<ComTopic<VxCard>> newTopics = Cache.getTinode().getFilteredTopics(t ->
68-
t.getTopicType().match(ComTopic.TopicType.USER) && mTopicFilter.filter((ComTopic) t));
74+
t.getTopicType().match(ComTopic.TopicType.USER) &&
75+
mTopicFilter.filter((ComTopic) t) &&
76+
mTextFilter.filter((ComTopic) t));
6977

7078
final HashMap<String, Integer> newTopicIndex = new HashMap<>(newTopics.size());
7179
for (ComTopic t : newTopics) {
@@ -140,6 +148,30 @@ void setSelectionTracker(SelectionTracker<String> selectionTracker) {
140148
mSelectionTracker = selectionTracker;
141149
}
142150

151+
void setTextFilter(@Nullable String text) {
152+
mTextFilter = new Filter() {
153+
private final String mQuery = text;
154+
@Override
155+
public boolean filter(ComTopic topic) {
156+
if (TextUtils.isEmpty(mQuery)) {
157+
return true;
158+
}
159+
160+
ArrayList<String> hayStack = new ArrayList<>();
161+
TheCard pub = (TheCard) topic.getPub();
162+
if (pub != null) {
163+
hayStack.add(pub.fn);
164+
hayStack.add(pub.note);
165+
}
166+
hayStack.add(topic.getComment());
167+
return hayStack.stream()
168+
.filter(token -> token != null && token.toLowerCase(Locale.getDefault()).contains(mQuery))
169+
.findAny()
170+
.orElse(null) != null;
171+
}
172+
};
173+
}
174+
143175
interface ClickListener {
144176
void onClick(String topicName);
145177
}

app/src/main/java/co/tinode/tindroid/SendToActivity.java

Lines changed: 157 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,37 @@
11
package co.tinode.tindroid;
22

3+
import android.app.Activity;
4+
import android.app.SearchManager;
35
import android.content.Intent;
6+
import android.net.Uri;
47
import android.os.Bundle;
8+
import android.os.Handler;
9+
import android.text.TextUtils;
510
import android.util.Log;
11+
import android.view.Menu;
12+
import android.view.MenuInflater;
13+
import android.view.MenuItem;
14+
import android.widget.SearchView;
615

16+
import java.util.Locale;
17+
18+
import androidx.annotation.NonNull;
719
import androidx.appcompat.app.ActionBar;
820
import androidx.appcompat.app.AppCompatActivity;
921
import androidx.appcompat.widget.Toolbar;
22+
import androidx.recyclerview.widget.LinearLayoutManager;
23+
import androidx.recyclerview.widget.RecyclerView;
24+
import co.tinode.tindroid.widgets.HorizontalListDivider;
25+
import co.tinode.tinodesdk.Topic;
1026

11-
public class SendToActivity extends AppCompatActivity
12-
implements FindFragment.ReadContactsPermissionChecker {
27+
public class SendToActivity extends AppCompatActivity {
1328
private static final String TAG = "SendToActivity";
1429

15-
// Limit the number of times permissions are requested per session.
16-
private boolean mReadContactsPermissionsAlreadyRequested = false;
30+
// Delay in milliseconds between the last keystroke and time when the query is sent to the server.
31+
private static final int SEARCH_REQUEST_DELAY = 1000;
32+
33+
private ChatsAdapter mAdapter = null;
34+
private String mSearchTerm; // Stores the current search query term
1735

1836
@Override
1937
public void onCreate(Bundle savedInstanceState) {
@@ -46,17 +64,144 @@ public void onCreate(Bundle savedInstanceState) {
4664
});
4765
}
4866

49-
getSupportFragmentManager()
50-
.beginTransaction()
51-
.add(R.id.contentFragment, new FindFragment(), "contacts")
52-
.commitAllowingStateLoss();
67+
RecyclerView rv = findViewById(R.id.chat_list);
68+
rv.setLayoutManager(new LinearLayoutManager(this));
69+
rv.setHasFixedSize(true);
70+
rv.addItemDecoration(new HorizontalListDivider(this));
71+
mAdapter = new ChatsAdapter(this, topicName -> {
72+
if (isFinishing() || isDestroyed()) {
73+
return;
74+
}
75+
Intent launcher = new Intent(this, MessageActivity.class);
76+
Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
77+
if (uri != null) {
78+
launcher.setDataAndType(uri, intent.getType());
79+
launcher.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
80+
}
81+
launcher.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
82+
launcher.putExtra("topic", topicName);
83+
startActivity(launcher);
84+
finish();
85+
}, Topic::isWriter);
86+
rv.setAdapter(mAdapter);
5387
}
5488

55-
public boolean shouldRequestReadContactsPermission() {
56-
return !mReadContactsPermissionsAlreadyRequested;
89+
@Override
90+
public void onResume() {
91+
super.onResume();
92+
mAdapter.resetContent(this);
93+
}
94+
95+
@Override
96+
public boolean onCreateOptionsMenu(Menu menu) {
97+
final SearchManager searchManager = (SearchManager) getSystemService(Activity.SEARCH_SERVICE);
98+
if (searchManager == null) {
99+
return false;
100+
}
101+
102+
MenuInflater inflater = getMenuInflater();
103+
menu.clear();
104+
inflater.inflate(R.menu.menu_search, menu);
105+
106+
// Setting up SearchView
107+
108+
// Locate the search item
109+
MenuItem searchItem = menu.findItem(R.id.action_search);
110+
111+
// Retrieves the SearchView from the search menu item
112+
final SearchView searchView = (SearchView) searchItem.getActionView();
113+
if (searchView == null) {
114+
return false;
115+
}
116+
searchView.setQueryHint(getResources().getString(R.string.hint_search_tags));
117+
// Assign searchable info to SearchView
118+
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
119+
searchView.setFocusable(true);
120+
searchView.setFocusableInTouchMode(true);
121+
122+
// Set listeners for SearchView
123+
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
124+
private Handler mHandler;
125+
126+
@Override
127+
public boolean onQueryTextSubmit(String queryText) {
128+
if (mHandler != null) {
129+
mHandler.removeCallbacksAndMessages(null);
130+
}
131+
132+
mSearchTerm = doSearch(queryText);
133+
134+
return true;
135+
}
136+
137+
@Override
138+
public boolean onQueryTextChange(final String queryText) {
139+
140+
if (mHandler == null) {
141+
mHandler = new Handler();
142+
} else {
143+
mHandler.removeCallbacksAndMessages(null);
144+
}
145+
146+
// Delay search in case of more input
147+
mHandler.postDelayed(() -> mSearchTerm = doSearch(queryText), SEARCH_REQUEST_DELAY);
148+
return true;
149+
}
150+
});
151+
152+
searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
153+
@Override
154+
public boolean onMenuItemActionExpand(@NonNull MenuItem menuItem) {
155+
searchView.setIconified(false);
156+
searchView.requestFocus();
157+
searchView.requestFocusFromTouch();
158+
return true;
159+
}
160+
161+
@Override
162+
public boolean onMenuItemActionCollapse(@NonNull MenuItem menuItem) {
163+
searchView.clearFocus();
164+
mSearchTerm = null;
165+
return true;
166+
}
167+
});
168+
169+
170+
if (mSearchTerm != null) {
171+
// If search term is already set here then this fragment is
172+
// being restored from a saved state and the search menu item
173+
// needs to be expanded and populated again.
174+
175+
// Stores the search term (as it will be wiped out by
176+
// onQueryTextChange() when the menu item is expanded).
177+
final String savedSearchTerm = mSearchTerm;
178+
179+
// Expands the search menu item
180+
searchItem.expandActionView();
181+
182+
// Sets the SearchView to the previous search string
183+
searchView.setQuery(savedSearchTerm, false);
184+
}
185+
return true;
57186
}
58187

59-
public void setReadContactsPermissionRequested() {
60-
mReadContactsPermissionsAlreadyRequested = true;
188+
private String doSearch(String query) {
189+
query = query.trim().toLowerCase(Locale.getDefault());
190+
query = !TextUtils.isEmpty(query) ? query : null;
191+
192+
// No change.
193+
if (mSearchTerm == null && query == null) {
194+
return null;
195+
}
196+
197+
// Don't do anything if the new filter is the same as the current filter
198+
if (mSearchTerm != null && mSearchTerm.equals(query)) {
199+
return mSearchTerm;
200+
}
201+
202+
mAdapter.setTextFilter(query);
203+
mAdapter.resetContent(this);
204+
205+
return query;
61206
}
62207
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:height="24dp"
3+
android:width="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
android:fillColor="#000"
8+
android:pathData="M12,5A3.5,3.5 0 0,0 8.5,8.5A3.5,3.5 0 0,0 12,12A3.5,3.5 0 0,0 15.5,8.5A3.5,3.5 0 0,0 12,5M12,7A1.5,1.5 0 0,1 13.5,8.5A1.5,1.5 0 0,1 12,10A1.5,1.5 0 0,1 10.5,8.5A1.5,1.5 0 0,1 12,7M5.5,8A2.5,2.5 0 0,0 3,10.5C3,11.44 3.53,12.25 4.29,12.68C4.65,12.88 5.06,13 5.5,13C5.94,13 6.35,12.88 6.71,12.68C7.08,12.47 7.39,12.17 7.62,11.81C6.89,10.86 6.5,9.7 6.5,8.5C6.5,8.41 6.5,8.31 6.5,8.22C6.2,8.08 5.86,8 5.5,8M18.5,8C18.14,8 17.8,8.08 17.5,8.22C17.5,8.31 17.5,8.41 17.5,8.5C17.5,9.7 17.11,10.86 16.38,11.81C16.5,12 16.63,12.15 16.78,12.3C16.94,12.45 17.1,12.58 17.29,12.68C17.65,12.88 18.06,13 18.5,13C18.94,13 19.35,12.88 19.71,12.68C20.47,12.25 21,11.44 21,10.5A2.5,2.5 0 0,0 18.5,8M12,14C9.66,14 5,15.17 5,17.5V19H19V17.5C19,15.17 14.34,14 12,14M4.71,14.55C2.78,14.78 0,15.76 0,17.5V19H3V17.07C3,16.06 3.69,15.22 4.71,14.55M19.29,14.55C20.31,15.22 21,16.06 21,17.07V19H24V17.5C24,15.76 21.22,14.78 19.29,14.55M12,16C13.53,16 15.24,16.5 16.23,17H7.77C8.76,16.5 10.47,16 12,16Z" />
9+
</vector>

app/src/main/res/layout/activity_send_to.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
<include layout="@layout/toolbar" />
1111

12-
<FrameLayout
13-
android:id="@+id/contentFragment"
12+
<androidx.recyclerview.widget.RecyclerView
13+
android:id="@+id/chat_list"
1414
android:layout_width="match_parent"
1515
android:layout_height="match_parent"/>
1616

app/src/main/res/menu/menu_search.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<menu xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto">
4+
<item
5+
android:id="@+id/action_search"
6+
android:icon="@drawable/ic_search"
7+
android:orderInCategory="100"
8+
android:title="@string/action_search"
9+
app:actionViewClass="android.widget.SearchView"
10+
app:showAsAction="ifRoom|collapseActionView"/>
11+
</menu>

0 commit comments

Comments
 (0)