mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-17 04:00:48 +01:00
improved trends location dialog
This commit is contained in:
parent
c9e241d7d3
commit
8406a55f01
@ -30,12 +30,14 @@ public class Location {
|
||||
|
||||
@JsonField(name = "woeid")
|
||||
int woeid;
|
||||
@JsonField(name = "parentid")
|
||||
int parentId;
|
||||
@JsonField(name = "country")
|
||||
String countryName;
|
||||
@JsonField(name = "countryCode")
|
||||
String countryCode;
|
||||
@JsonField(name = "placeType")
|
||||
PlaceTypeImpl placeType;
|
||||
PlaceType placeType;
|
||||
@JsonField(name = "name")
|
||||
String name;
|
||||
@JsonField(name = "url")
|
||||
@ -45,6 +47,10 @@ public class Location {
|
||||
return woeid;
|
||||
}
|
||||
|
||||
public long getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public String getCountryName() {
|
||||
return countryName;
|
||||
}
|
||||
@ -53,7 +59,7 @@ public class Location {
|
||||
return countryCode;
|
||||
}
|
||||
|
||||
public PlaceTypeImpl getPlaceType() {
|
||||
public PlaceType getPlaceType() {
|
||||
return placeType;
|
||||
}
|
||||
|
||||
@ -65,11 +71,27 @@ public class Location {
|
||||
return url;
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
public static class PlaceTypeImpl {
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Location location = (Location) o;
|
||||
|
||||
return woeid == location.woeid;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return woeid;
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
public static class PlaceType {
|
||||
@JsonField(name = "name")
|
||||
String name;
|
||||
|
||||
@JsonField(name = "code")
|
||||
int code;
|
||||
|
||||
@ -80,5 +102,13 @@ public class Location {
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlaceType{" +
|
||||
"name='" + name + '\'' +
|
||||
", code=" + code +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,42 +19,47 @@
|
||||
|
||||
package org.mariotaku.twidere.preference;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
import android.support.v4.util.SimpleArrayMap;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.BaseExpandableListAdapter;
|
||||
import android.widget.ExpandableListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.twidere.BuildConfig;
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Location;
|
||||
import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
||||
import org.mariotaku.twidere.util.TwitterAPIFactory;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class TrendsLocationPreference extends Preference implements Constants, OnClickListener {
|
||||
|
||||
private int mCheckedWoeId = 1;
|
||||
public class TrendsLocationPreference extends Preference implements Constants {
|
||||
|
||||
private static final long EMPTY = 0;
|
||||
private static final long WORLDWIDE = 1;
|
||||
private final ExpandableTrendLocationsListAdapter mAdapter;
|
||||
private GetAvailableTrendsTask mGetAvailableTrendsTask;
|
||||
|
||||
private final AvailableTrendsAdapter mAdapter;
|
||||
|
||||
private AlertDialog mDialog;
|
||||
|
||||
public TrendsLocationPreference(final Context context) {
|
||||
@ -67,23 +72,11 @@ public class TrendsLocationPreference extends Preference implements Constants, O
|
||||
|
||||
public TrendsLocationPreference(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mAdapter = new AvailableTrendsAdapter(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
final Location item = mAdapter.getItem(which);
|
||||
if (item != null) {
|
||||
persistInt(item.getWoeid());
|
||||
}
|
||||
if (mDialog != null && mDialog.isShowing()) {
|
||||
mDialog.dismiss();
|
||||
}
|
||||
mAdapter = new ExpandableTrendLocationsListAdapter(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
mCheckedWoeId = getPersistedInt(1);
|
||||
if (mGetAvailableTrendsTask != null) {
|
||||
mGetAvailableTrendsTask.cancel(false);
|
||||
}
|
||||
@ -91,64 +84,178 @@ public class TrendsLocationPreference extends Preference implements Constants, O
|
||||
mGetAvailableTrendsTask.execute();
|
||||
}
|
||||
|
||||
private static class AvailableTrendsAdapter extends ArrayAdapter<Location> {
|
||||
static class ExpandableTrendLocationsListAdapter extends BaseExpandableListAdapter {
|
||||
|
||||
private final Context mContext;
|
||||
private final LayoutInflater mInflater;
|
||||
@Nullable
|
||||
SimpleArrayMap<Location, List<Location>> mData;
|
||||
|
||||
public AvailableTrendsAdapter(final Context context) {
|
||||
super(context, android.R.layout.simple_list_item_single_choice);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public int findItemPosition(final int woeid) {
|
||||
final int count = getCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final Location item = getItem(i);
|
||||
if (item.getWoeid() == woeid) return i;
|
||||
}
|
||||
return -1;
|
||||
public ExpandableTrendLocationsListAdapter(Context context) {
|
||||
mInflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, final View convertView, final ViewGroup parent) {
|
||||
final View view = super.getView(position, convertView, parent);
|
||||
final TextView text = (TextView) (view instanceof TextView ? view : view.findViewById(android.R.id.text1));
|
||||
final Location item = getItem(position);
|
||||
if (item != null && text != null) {
|
||||
text.setSingleLine();
|
||||
text.setText(item.getName());
|
||||
public int getGroupCount() {
|
||||
if (mData == null) return 0;
|
||||
return mData.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildrenCount(int groupPosition) {
|
||||
if (mData == null) return 0;
|
||||
return mData.valueAt(groupPosition).size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getGroup(int groupPosition) {
|
||||
assert mData != null;
|
||||
return mData.keyAt(groupPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getChild(int groupPosition, int childPosition) {
|
||||
assert mData != null;
|
||||
return mData.valueAt(groupPosition).get(childPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getGroupId(int groupPosition) {
|
||||
return getGroup(groupPosition).getWoeid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChildId(int groupPosition, int childPosition) {
|
||||
return getChild(groupPosition, childPosition).getWoeid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null) {
|
||||
view = convertView;
|
||||
} else {
|
||||
view = mInflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false);
|
||||
}
|
||||
((TextView) view.findViewById(android.R.id.text1)).setText(getGroup(groupPosition).getName());
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null) {
|
||||
view = convertView;
|
||||
} else {
|
||||
view = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
|
||||
}
|
||||
final Location location = getChild(groupPosition, childPosition);
|
||||
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
|
||||
if (location.getParentId() == 1) {
|
||||
text1.setText(R.string.location_countrywide);
|
||||
} else {
|
||||
text1.setText(location.getName());
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
public void setData(final List<Location> data) {
|
||||
clear();
|
||||
if (data != null) {
|
||||
addAll(data);
|
||||
}
|
||||
sort(new LocationComparator(mContext));
|
||||
@Override
|
||||
public boolean isChildSelectable(int groupPosition, int childPosition) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setData(@Nullable SimpleArrayMap<Location, List<Location>> data) {
|
||||
mData = data;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
static class LocationsMap {
|
||||
|
||||
final LongSparseArray<List<Location>> map = new LongSparseArray<>();
|
||||
final LongSparseArray<Location> parents = new LongSparseArray<>();
|
||||
private final LocationComparator comparator;
|
||||
|
||||
LocationsMap(Locale locale) {
|
||||
comparator = new LocationComparator(Collator.getInstance(locale));
|
||||
}
|
||||
|
||||
void put(Location location) {
|
||||
final long parentId = location.getParentId();
|
||||
if (parentId == EMPTY || parentId == WORLDWIDE) {
|
||||
putParent(location);
|
||||
} else {
|
||||
putChild(parentId, location);
|
||||
}
|
||||
}
|
||||
|
||||
void putParent(Location location) {
|
||||
final long woeid = location.getWoeid();
|
||||
parents.put(woeid, location);
|
||||
final List<Location> list = getList(woeid);
|
||||
// Don't add child for 'worldwide'
|
||||
if (woeid != WORLDWIDE) {
|
||||
addToList(list, location);
|
||||
}
|
||||
}
|
||||
|
||||
void putChild(long parentId, Location location) {
|
||||
addToList(getList(parentId), location);
|
||||
}
|
||||
|
||||
List<Location> getList(long parentId) {
|
||||
List<Location> list = map.get(parentId);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
map.put(parentId, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void addToList(List<Location> list, Location location) {
|
||||
int loc = Collections.binarySearch(list, location, comparator);
|
||||
if (loc < 0) {
|
||||
list.add(-(loc + 1), location);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleArrayMap<Location, List<Location>> pack() {
|
||||
SimpleArrayMap<Location, List<Location>> result = new SimpleArrayMap<>(map.size());
|
||||
for (int i = 0, j = map.size(); i < j; i++) {
|
||||
Location parent = parents.get(map.keyAt(i));
|
||||
if (parent == null) continue;
|
||||
result.put(parent, map.valueAt(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class LocationComparator implements Comparator<Location> {
|
||||
private final Collator mCollator;
|
||||
private final Collator collator;
|
||||
|
||||
LocationComparator(final Context context) {
|
||||
mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
|
||||
public LocationComparator(Collator collator) {
|
||||
this.collator = collator;
|
||||
}
|
||||
|
||||
private boolean isCountryOrWorldwide(Location location) {
|
||||
final long parentId = location.getParentId();
|
||||
return parentId == 0 || parentId == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(final Location object1, final Location object2) {
|
||||
if (object1.getWoeid() == 1) return Integer.MIN_VALUE;
|
||||
if (object2.getWoeid() == 1) return Integer.MAX_VALUE;
|
||||
return mCollator.compare(object1.getName(), object2.getName());
|
||||
public int compare(Location lhs, Location rhs) {
|
||||
if (isCountryOrWorldwide(lhs)) return Integer.MIN_VALUE;
|
||||
if (isCountryOrWorldwide(rhs)) return Integer.MAX_VALUE;
|
||||
return collator.compare(lhs.getName(), rhs.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class GetAvailableTrendsTask extends AsyncTask<Object, Object, ResponseList<Location>> implements OnCancelListener {
|
||||
|
||||
class GetAvailableTrendsTask extends AsyncTask<Object, Object, SimpleArrayMap<Location,
|
||||
List<Location>>> implements OnCancelListener {
|
||||
private final ProgressDialog mProgress;
|
||||
|
||||
public GetAvailableTrendsTask(final Context context) {
|
||||
@ -161,19 +268,25 @@ public class TrendsLocationPreference extends Preference implements Constants, O
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResponseList<Location> doInBackground(final Object... args) {
|
||||
protected SimpleArrayMap<Location, List<Location>> doInBackground(final Object... args) {
|
||||
final Twitter twitter = TwitterAPIFactory.getDefaultTwitterInstance(getContext(), false);
|
||||
if (twitter == null) return null;
|
||||
try {
|
||||
return twitter.getAvailableTrends();
|
||||
LocationsMap map = new LocationsMap(Locale.getDefault());
|
||||
for (Location location : twitter.getAvailableTrends()) {
|
||||
map.put(location);
|
||||
}
|
||||
return map.pack();
|
||||
} catch (final TwitterException e) {
|
||||
Log.w(LOGTAG, e);
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.w(LOGTAG, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final ResponseList<Location> result) {
|
||||
protected void onPostExecute(final SimpleArrayMap<Location, List<Location>> result) {
|
||||
if (mProgress.isShowing()) {
|
||||
mProgress.dismiss();
|
||||
}
|
||||
@ -181,14 +294,38 @@ public class TrendsLocationPreference extends Preference implements Constants, O
|
||||
if (result == null) return;
|
||||
final AlertDialog.Builder selectorBuilder = new AlertDialog.Builder(getContext());
|
||||
selectorBuilder.setTitle(getTitle());
|
||||
selectorBuilder.setSingleChoiceItems(mAdapter, mAdapter.findItemPosition(mCheckedWoeId),
|
||||
TrendsLocationPreference.this);
|
||||
selectorBuilder.setView(R.layout.dialog_trends_location_selector);
|
||||
selectorBuilder.setNegativeButton(android.R.string.cancel, null);
|
||||
mDialog = selectorBuilder.create();
|
||||
final ListView lv = mDialog.getListView();
|
||||
if (lv != null) {
|
||||
lv.setFastScrollEnabled(true);
|
||||
}
|
||||
mDialog.setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
@Override
|
||||
public void onShow(DialogInterface dialogInterface) {
|
||||
final Dialog dialog = (Dialog) dialogInterface;
|
||||
final ExpandableListView listView = (ExpandableListView) dialog.findViewById(R.id.expandable_list);
|
||||
listView.setAdapter(mAdapter);
|
||||
listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
|
||||
@Override
|
||||
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
|
||||
final Location group = mAdapter.getGroup(groupPosition);
|
||||
if (group.getWoeid() == WORLDWIDE) {
|
||||
persistInt(group.getWoeid());
|
||||
dialog.dismiss();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
|
||||
@Override
|
||||
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
|
||||
final Location child = mAdapter.getChild(groupPosition, childPosition);
|
||||
persistInt(child.getWoeid());
|
||||
dialog.dismiss();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
mDialog.show();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ExpandableListView
|
||||
android:id="@+id/expandable_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</FrameLayout>
|
@ -785,4 +785,5 @@
|
||||
<!-- GNU social group like https://quitter.se/group/qvitter -->
|
||||
<string name="group">Group</string>
|
||||
<string name="your_coarse_location">Your coarse location</string>
|
||||
<string name="location_countrywide">Countrywide</string>
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user