using separate trends location
This commit is contained in:
parent
8685437b85
commit
0813eb907a
|
@ -210,4 +210,7 @@ public interface IntentConstants {
|
|||
String EXTRA_REQUEST_CODE = "request_code";
|
||||
String EXTRA_FROM_CACHE = "from_cache";
|
||||
String EXTRA_SHOW_MY_LISTS = "show_my_lists";
|
||||
String EXTRA_WOEID = "woeid";
|
||||
String EXTRA_PLACE = "place";
|
||||
String EXTRA_PLACE_NAME = "place_name";
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.mariotaku.twidere.model.tab.argument.UserListArguments;
|
|||
import org.mariotaku.twidere.model.tab.extra.HomeTabExtras;
|
||||
import org.mariotaku.twidere.model.tab.extra.InteractionsTabExtras;
|
||||
import org.mariotaku.twidere.model.tab.extra.TabExtras;
|
||||
import org.mariotaku.twidere.model.tab.extra.TrendsTabExtras;
|
||||
import org.mariotaku.twidere.model.util.TabArgumentsFieldConverter;
|
||||
import org.mariotaku.twidere.model.util.TabExtrasFieldConverter;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
|
||||
|
@ -260,15 +261,19 @@ public class Tab implements Parcelable {
|
|||
@JsonField(name = "home")
|
||||
@ParcelableThisPlease
|
||||
HomeTabExtras home;
|
||||
@JsonField(name = "trends")
|
||||
@ParcelableThisPlease
|
||||
TrendsTabExtras trends;
|
||||
|
||||
public static InternalExtras from(TabExtras extras) {
|
||||
if (extras == null) return null;
|
||||
InternalExtras result = new InternalExtras();
|
||||
if (extras instanceof InteractionsTabExtras) {
|
||||
result.interactions = (InteractionsTabExtras) extras;
|
||||
}
|
||||
if (extras instanceof HomeTabExtras) {
|
||||
} else if (extras instanceof HomeTabExtras) {
|
||||
result.home = (HomeTabExtras) extras;
|
||||
} else if (extras instanceof TrendsTabExtras) {
|
||||
result.trends = (TrendsTabExtras) extras;
|
||||
} else {
|
||||
result.base = extras;
|
||||
}
|
||||
|
@ -280,6 +285,8 @@ public class Tab implements Parcelable {
|
|||
return interactions;
|
||||
} else if (home != null) {
|
||||
return home;
|
||||
} else if (trends != null) {
|
||||
return trends;
|
||||
} else {
|
||||
return base;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package org.mariotaku.twidere.model.tab.extra;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||
|
||||
import static org.mariotaku.twidere.constant.IntentConstants.EXTRA_WOEID;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/2/2.
|
||||
*/
|
||||
|
||||
@JsonObject
|
||||
@ParcelablePlease
|
||||
public class TrendsTabExtras extends TabExtras implements Parcelable {
|
||||
@JsonField(name = "woeid")
|
||||
int woeId;
|
||||
@JsonField(name = "place_name")
|
||||
String placeName;
|
||||
|
||||
public String getPlaceName() {
|
||||
return placeName;
|
||||
}
|
||||
|
||||
public void setPlaceName(final String placeName) {
|
||||
this.placeName = placeName;
|
||||
}
|
||||
|
||||
public int getWoeId() {
|
||||
return woeId;
|
||||
}
|
||||
|
||||
public void setWoeId(final int woeId) {
|
||||
this.woeId = woeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyToBundle(final Bundle bundle) {
|
||||
super.copyToBundle(bundle);
|
||||
bundle.putInt(EXTRA_WOEID, woeId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
TrendsTabExtrasParcelablePlease.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static final Creator<TrendsTabExtras> CREATOR = new Creator<TrendsTabExtras>() {
|
||||
public TrendsTabExtras createFromParcel(Parcel source) {
|
||||
TrendsTabExtras target = new TrendsTabExtras();
|
||||
TrendsTabExtrasParcelablePlease.readFromParcel(target, source);
|
||||
return target;
|
||||
}
|
||||
|
||||
public TrendsTabExtras[] newArray(int size) {
|
||||
return new TrendsTabExtras[size];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -397,6 +397,10 @@
|
|||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.TrendsLocationSelectorActivity"
|
||||
android:label="@string/trends_location"
|
||||
android:theme="@style/Theme.Twidere.NoDisplay"/>
|
||||
<activity
|
||||
android:name=".activity.DataExportActivity"
|
||||
android:label="@string/export_settings"
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
package org.mariotaku.twidere.model.tab.impl;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.fragment.TrendsSuggestionsFragment;
|
||||
import org.mariotaku.twidere.model.Tab;
|
||||
import org.mariotaku.twidere.model.tab.DrawableHolder;
|
||||
import org.mariotaku.twidere.model.tab.StringHolder;
|
||||
import org.mariotaku.twidere.model.tab.TabConfiguration;
|
||||
import org.mariotaku.twidere.model.tab.conf.PlaceExtraConfiguration;
|
||||
import org.mariotaku.twidere.model.tab.extra.TrendsTabExtras;
|
||||
|
||||
import static org.mariotaku.twidere.constant.IntentConstants.EXTRA_PLACE;
|
||||
import static org.mariotaku.twidere.constant.IntentConstants.EXTRA_WOEID;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2016/11/27.
|
||||
|
@ -29,7 +37,56 @@ public class TrendsTabConfiguration extends TabConfiguration {
|
|||
@AccountFlags
|
||||
@Override
|
||||
public int getAccountFlags() {
|
||||
return FLAG_HAS_ACCOUNT;
|
||||
return FLAG_HAS_ACCOUNT | FLAG_ACCOUNT_REQUIRED | FLAG_ACCOUNT_MUTABLE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ExtraConfiguration[] getExtraConfigurations(Context context) {
|
||||
return new ExtraConfiguration[]{
|
||||
new PlaceExtraConfiguration(EXTRA_WOEID).title(R.string.trends_location).mutable(true),
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyExtraConfigurationTo(@NonNull Tab tab, @NonNull ExtraConfiguration extraConf) {
|
||||
final TrendsTabExtras extras = (TrendsTabExtras) tab.getExtras();
|
||||
assert extras != null;
|
||||
switch (extraConf.getKey()) {
|
||||
case EXTRA_PLACE: {
|
||||
PlaceExtraConfiguration conf = (PlaceExtraConfiguration) extraConf;
|
||||
PlaceExtraConfiguration.Place place = conf.getValue();
|
||||
if (place != null) {
|
||||
extras.setWoeId(place.getWoeId());
|
||||
extras.setPlaceName(place.getName());
|
||||
} else {
|
||||
extras.setWoeId(0);
|
||||
extras.setPlaceName(null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readExtraConfigurationFrom(@NonNull Tab tab, @NonNull ExtraConfiguration extraConf) {
|
||||
final TrendsTabExtras extras = (TrendsTabExtras) tab.getExtras();
|
||||
if (extras == null) return false;
|
||||
switch (extraConf.getKey()) {
|
||||
case EXTRA_PLACE: {
|
||||
final int woeId = extras.getWoeId();
|
||||
final String name = extras.getPlaceName();
|
||||
if (name != null) {
|
||||
PlaceExtraConfiguration.Place place = new PlaceExtraConfiguration.Place(woeId, name);
|
||||
((PlaceExtraConfiguration) extraConf).setValue(place);
|
||||
} else {
|
||||
((PlaceExtraConfiguration) extraConf).setValue(null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
|
@ -1,341 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.preference;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
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.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseExpandableListAdapter;
|
||||
import android.widget.ExpandableListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.microblog.library.MicroBlog;
|
||||
import org.mariotaku.microblog.library.MicroBlogException;
|
||||
import org.mariotaku.microblog.library.twitter.model.Location;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.util.DebugLog;
|
||||
import org.mariotaku.twidere.util.MicroBlogAPIFactory;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.mariotaku.twidere.TwidereConstants.LOGTAG;
|
||||
|
||||
public class TrendsLocationPreference extends Preference {
|
||||
|
||||
private static final long EMPTY = 0;
|
||||
private static final long WORLDWIDE = 1;
|
||||
private final ExpandableTrendLocationsListAdapter mAdapter;
|
||||
private GetAvailableTrendsTask mGetAvailableTrendsTask;
|
||||
private AlertDialog mDialog;
|
||||
|
||||
public TrendsLocationPreference(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public TrendsLocationPreference(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.preferenceStyle);
|
||||
}
|
||||
|
||||
public TrendsLocationPreference(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mAdapter = new ExpandableTrendLocationsListAdapter(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
if (mGetAvailableTrendsTask != null) {
|
||||
mGetAvailableTrendsTask.cancel(false);
|
||||
}
|
||||
mGetAvailableTrendsTask = new GetAvailableTrendsTask(getContext());
|
||||
mGetAvailableTrendsTask.execute();
|
||||
}
|
||||
|
||||
static class ExpandableTrendLocationsListAdapter extends BaseExpandableListAdapter {
|
||||
|
||||
private final LayoutInflater mInflater;
|
||||
@Nullable
|
||||
SimpleArrayMap<Location, List<Location>> mData;
|
||||
|
||||
public ExpandableTrendLocationsListAdapter(Context context) {
|
||||
mInflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@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 collator;
|
||||
|
||||
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(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, SimpleArrayMap<Location,
|
||||
List<Location>>> implements OnCancelListener {
|
||||
private final ProgressDialog mProgress;
|
||||
|
||||
public GetAvailableTrendsTask(final Context context) {
|
||||
mProgress = new ProgressDialog(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(final DialogInterface dialog) {
|
||||
cancel(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SimpleArrayMap<Location, List<Location>> doInBackground(final Object... args) {
|
||||
final MicroBlog twitter = MicroBlogAPIFactory.getDefaultTwitterInstance(getContext());
|
||||
if (twitter == null) return null;
|
||||
try {
|
||||
LocationsMap map = new LocationsMap(Locale.getDefault());
|
||||
for (Location location : twitter.getAvailableTrends()) {
|
||||
map.put(location);
|
||||
}
|
||||
return map.pack();
|
||||
} catch (final MicroBlogException e) {
|
||||
DebugLog.w(LOGTAG, null, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final SimpleArrayMap<Location, List<Location>> result) {
|
||||
if (mProgress.isShowing()) {
|
||||
mProgress.dismiss();
|
||||
}
|
||||
mAdapter.setData(result);
|
||||
if (result == null) return;
|
||||
final AlertDialog.Builder selectorBuilder = new AlertDialog.Builder(getContext());
|
||||
selectorBuilder.setTitle(getTitle());
|
||||
selectorBuilder.setView(R.layout.dialog_trends_location_selector);
|
||||
selectorBuilder.setNegativeButton(android.R.string.cancel, null);
|
||||
mDialog = selectorBuilder.create();
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (mProgress.isShowing()) {
|
||||
mProgress.dismiss();
|
||||
}
|
||||
mProgress.setMessage(getContext().getString(R.string.message_please_wait));
|
||||
mProgress.setOnCancelListener(this);
|
||||
mProgress.show();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -39,4 +39,8 @@ operator fun Bundle.set(key: String, value: Array<out Parcelable>?) {
|
|||
|
||||
operator fun Bundle.set(key: String, value: Array<String>?) {
|
||||
return putStringArray(key, value)
|
||||
}
|
||||
|
||||
fun <T> Bundle.getTypedArray(key: String, creator: Parcelable.Creator<T>): Array<T> {
|
||||
return getParcelableArray(key).toTypedArray(creator)
|
||||
}
|
|
@ -65,6 +65,7 @@ import org.mariotaku.abstask.library.TaskStarter
|
|||
import org.mariotaku.commons.io.StreamUtils
|
||||
import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.ktextension.checkAnySelfPermissionsGranted
|
||||
import org.mariotaku.ktextension.getTypedArray
|
||||
import org.mariotaku.ktextension.setItemChecked
|
||||
import org.mariotaku.ktextension.toTypedArray
|
||||
import org.mariotaku.pickncrop.library.MediaPickerActivity
|
||||
|
@ -558,7 +559,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
|
||||
if (savedInstanceState != null) {
|
||||
// Restore from previous saved state
|
||||
val selected = savedInstanceState.getParcelableArray(EXTRA_ACCOUNT_KEYS).toTypedArray(UserKey.CREATOR)
|
||||
val selected = savedInstanceState.getTypedArray(EXTRA_ACCOUNT_KEYS, UserKey.CREATOR)
|
||||
accountsAdapter.setSelectedAccountIds(*selected)
|
||||
possiblySensitive = savedInstanceState.getBoolean(EXTRA_IS_POSSIBLY_SENSITIVE)
|
||||
val mediaList = savedInstanceState.getParcelableArrayList<ParcelableMediaUpdate>(EXTRA_MEDIA)
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
package org.mariotaku.twidere.activity
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.support.v4.app.DialogFragment
|
||||
import android.support.v4.util.LongSparseArray
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.BaseExpandableListAdapter
|
||||
import android.widget.ExpandableListView
|
||||
import android.widget.TextView
|
||||
import nl.komponents.kovenant.task
|
||||
import nl.komponents.kovenant.ui.alwaysUi
|
||||
import nl.komponents.kovenant.ui.failUi
|
||||
import nl.komponents.kovenant.ui.successUi
|
||||
import org.mariotaku.ktextension.getTypedArray
|
||||
import org.mariotaku.ktextension.set
|
||||
import org.mariotaku.microblog.library.MicroBlogException
|
||||
import org.mariotaku.microblog.library.twitter.model.Location
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_KEY
|
||||
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_DATA
|
||||
import org.mariotaku.twidere.fragment.BaseDialogFragment
|
||||
import org.mariotaku.twidere.fragment.ProgressDialogFragment
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.util.MicroBlogAPIFactory
|
||||
import java.lang.ref.WeakReference
|
||||
import java.text.Collator
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/2/2.
|
||||
*/
|
||||
|
||||
class TrendsLocationSelectorActivity : BaseActivity() {
|
||||
|
||||
private val accountKey: UserKey?
|
||||
get() = intent.getParcelableExtra<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val accountKey = this.accountKey ?: run {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) return
|
||||
val weakThis = WeakReference(this)
|
||||
val weakPd = WeakReference(ProgressDialogFragment.show(supportFragmentManager, PROGRESS_FRAGMENT_TAG).apply {
|
||||
isCancelable = false
|
||||
})
|
||||
task {
|
||||
val activity = weakThis.get() ?: throw InterruptedException()
|
||||
val twitter = MicroBlogAPIFactory.getInstance(activity, accountKey)
|
||||
?: throw MicroBlogException("No account")
|
||||
val map = LocationsMap(Locale.getDefault())
|
||||
twitter.availableTrends.forEach { location -> map.put(location) }
|
||||
return@task map.pack()
|
||||
}.successUi { result ->
|
||||
val df = TrendsLocationDialogFragment()
|
||||
df.arguments = org.mariotaku.ktextension.Bundle {
|
||||
this[EXTRA_DATA] = result
|
||||
}
|
||||
df.show(supportFragmentManager, "trends_location_selector")
|
||||
}.failUi {
|
||||
val activity = weakThis.get() ?: return@failUi
|
||||
activity.finish()
|
||||
}.alwaysUi {
|
||||
val activity = weakThis.get() ?: return@alwaysUi
|
||||
activity.executeAfterFragmentResumed { activity ->
|
||||
val df = weakPd.get() ?: activity.supportFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG) as? DialogFragment
|
||||
df?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TrendsLocationDialogFragment : BaseDialogFragment() {
|
||||
private val list: Array<LocationsMap.LocationsData> get() = arguments.getTypedArray(EXTRA_DATA,
|
||||
LocationsMap.LocationsData.CREATOR)
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val selectorBuilder = AlertDialog.Builder(context)
|
||||
selectorBuilder.setTitle(R.string.trends_location)
|
||||
selectorBuilder.setView(R.layout.dialog_trends_location_selector)
|
||||
selectorBuilder.setNegativeButton(android.R.string.cancel, null)
|
||||
val dialog = selectorBuilder.create()
|
||||
dialog.setOnShowListener { dialogInterface ->
|
||||
dialogInterface as Dialog
|
||||
val listView = dialogInterface.findViewById(R.id.expandable_list) as ExpandableListView
|
||||
val adapter = ExpandableTrendLocationsListAdapter(context)
|
||||
adapter.data = list
|
||||
listView.setAdapter(adapter)
|
||||
listView.setOnGroupClickListener(ExpandableListView.OnGroupClickListener { parent, v, groupPosition, id ->
|
||||
val group = adapter.getGroup(groupPosition)
|
||||
if (group.woeid.toLong() == WORLDWIDE) {
|
||||
dismiss()
|
||||
return@OnGroupClickListener true
|
||||
}
|
||||
false
|
||||
})
|
||||
listView.setOnChildClickListener { parent, v, groupPosition, childPosition, id ->
|
||||
val child = adapter.getChild(groupPosition, childPosition)
|
||||
dismiss()
|
||||
return@setOnChildClickListener true
|
||||
}
|
||||
}
|
||||
dialog.show()
|
||||
return dialog
|
||||
}
|
||||
|
||||
override fun onDismiss(dialog: DialogInterface?) {
|
||||
super.onDismiss(dialog)
|
||||
activity?.finish()
|
||||
}
|
||||
|
||||
override fun onCancel(dialog: DialogInterface?) {
|
||||
super.onCancel(dialog)
|
||||
activity?.finish()
|
||||
}
|
||||
}
|
||||
|
||||
internal class ExpandableTrendLocationsListAdapter(context: Context) : BaseExpandableListAdapter() {
|
||||
|
||||
private val inflater = LayoutInflater.from(context)
|
||||
var data: Array<LocationsMap.LocationsData>? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun getGroupCount(): Int {
|
||||
return data?.size ?: 0
|
||||
}
|
||||
|
||||
override fun getChildrenCount(groupPosition: Int): Int {
|
||||
return data!![groupPosition].children.size
|
||||
}
|
||||
|
||||
override fun getGroup(groupPosition: Int): Location {
|
||||
return data!![groupPosition].root
|
||||
}
|
||||
|
||||
override fun getChild(groupPosition: Int, childPosition: Int): Location {
|
||||
return data!![groupPosition].children[childPosition]
|
||||
}
|
||||
|
||||
override fun getGroupId(groupPosition: Int): Long {
|
||||
return getGroup(groupPosition).woeid.toLong()
|
||||
}
|
||||
|
||||
override fun getChildId(groupPosition: Int, childPosition: Int): Long {
|
||||
return getChild(groupPosition, childPosition).woeid.toLong()
|
||||
}
|
||||
|
||||
override fun hasStableIds(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View {
|
||||
val view: View
|
||||
if (convertView != null) {
|
||||
view = convertView
|
||||
} else {
|
||||
view = inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false)
|
||||
}
|
||||
(view.findViewById(android.R.id.text1) as TextView).text = getGroup(groupPosition).name
|
||||
return view
|
||||
}
|
||||
|
||||
override fun getChildView(groupPosition: Int, childPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View {
|
||||
val view: View
|
||||
if (convertView != null) {
|
||||
view = convertView
|
||||
} else {
|
||||
view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
|
||||
}
|
||||
val location = getChild(groupPosition, childPosition)
|
||||
val text1 = view.findViewById(android.R.id.text1) as TextView
|
||||
if (location.parentId == WORLDWIDE) {
|
||||
text1.setText(R.string.location_countrywide)
|
||||
} else {
|
||||
text1.text = location.name
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class LocationComparator(private val collator: Collator) : Comparator<Location> {
|
||||
|
||||
private fun isCountryOrWorldwide(location: Location): Boolean {
|
||||
val parentId = location.parentId
|
||||
return parentId == EMPTY || parentId == WORLDWIDE
|
||||
}
|
||||
|
||||
override fun compare(lhs: Location, rhs: Location): Int {
|
||||
if (isCountryOrWorldwide(lhs)) return Integer.MIN_VALUE
|
||||
if (isCountryOrWorldwide(rhs)) return Integer.MAX_VALUE
|
||||
return collator.compare(lhs.name, rhs.name)
|
||||
}
|
||||
}
|
||||
|
||||
internal class LocationsMap(locale: Locale) {
|
||||
|
||||
val map = LongSparseArray<MutableList<Location>>()
|
||||
val parents = LongSparseArray<Location>()
|
||||
private val comparator = LocationComparator(Collator.getInstance(locale))
|
||||
|
||||
fun put(location: Location) {
|
||||
val parentId = location.parentId
|
||||
if (parentId == EMPTY || parentId == WORLDWIDE) {
|
||||
putParent(location)
|
||||
} else {
|
||||
putChild(parentId, location)
|
||||
}
|
||||
}
|
||||
|
||||
fun putParent(location: Location) {
|
||||
val woeid = location.woeid.toLong()
|
||||
parents.put(woeid, location)
|
||||
val list = getList(woeid)
|
||||
// Don't add child for 'worldwide'
|
||||
if (woeid != WORLDWIDE) {
|
||||
addToList(list, location)
|
||||
}
|
||||
}
|
||||
|
||||
fun putChild(parentId: Long, location: Location) {
|
||||
addToList(getList(parentId), location)
|
||||
}
|
||||
|
||||
fun getList(parentId: Long): MutableList<Location> {
|
||||
return map.get(parentId) ?: run {
|
||||
val l = ArrayList<Location>()
|
||||
map.put(parentId, l)
|
||||
return@run l
|
||||
}
|
||||
}
|
||||
|
||||
fun addToList(list: MutableList<Location>, location: Location) {
|
||||
val loc = Collections.binarySearch(list, location, comparator)
|
||||
if (loc < 0) {
|
||||
list.add(-(loc + 1), location)
|
||||
}
|
||||
}
|
||||
|
||||
fun pack(): Array<LocationsData> {
|
||||
return (0 until map.size()).mapNotNull { i ->
|
||||
val parent = parents.get(map.keyAt(i)) ?: return@mapNotNull null
|
||||
return@mapNotNull LocationsData(parent, map.valueAt(i).toTypedArray())
|
||||
}.toTypedArray()
|
||||
}
|
||||
|
||||
data class LocationsData(val root: Location, val children: Array<Location>) : Parcelable {
|
||||
override fun describeContents(): Int = 0
|
||||
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
dest.writeParcelable(root, flags)
|
||||
dest.writeTypedArray(children, flags)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CREATOR = object : Parcelable.Creator<LocationsData> {
|
||||
override fun createFromParcel(source: Parcel): LocationsData {
|
||||
val root = source.readParcelable<Location>(Location::class.java.classLoader)
|
||||
val children = source.createTypedArray(Location.CREATOR)
|
||||
return LocationsData(root, children)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<out LocationsData?> {
|
||||
return arrayOfNulls<LocationsData>(size)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PROGRESS_FRAGMENT_TAG = "load_location_progress"
|
||||
private const val EMPTY: Long = 0
|
||||
private const val WORLDWIDE: Long = 1
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ import com.squareup.otto.Subscribe
|
|||
import kotlinx.android.synthetic.main.fragment_content_listview.*
|
||||
import org.mariotaku.sqliteqb.library.*
|
||||
import org.mariotaku.twidere.adapter.TrendsAdapter
|
||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_LOCAL_TRENDS_WOEID
|
||||
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_WOEID
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.message.TrendsRefreshedEvent
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends
|
||||
|
@ -97,7 +97,7 @@ class TrendsSuggestionsFragment : AbsContentListViewFragment<TrendsAdapter>(), L
|
|||
|
||||
override fun onRefresh() {
|
||||
if (refreshing) return
|
||||
twitterWrapper.getLocalTrendsAsync(accountId, preferences.getInt(KEY_LOCAL_TRENDS_WOEID, 1))
|
||||
twitterWrapper.getLocalTrendsAsync(accountId, arguments.getInt(EXTRA_WOEID, 1))
|
||||
}
|
||||
|
||||
override var refreshing: Boolean
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package org.mariotaku.twidere.model.tab.conf
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.activity.TrendsLocationSelectorActivity
|
||||
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_KEY
|
||||
import org.mariotaku.twidere.fragment.CustomTabsFragment
|
||||
import org.mariotaku.twidere.model.tab.TabConfiguration
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2016/12/5.
|
||||
*/
|
||||
open class PlaceExtraConfiguration(
|
||||
key: String
|
||||
) : TabConfiguration.ExtraConfiguration(key) {
|
||||
|
||||
open var value: Place? = null
|
||||
|
||||
override fun onCreateView(context: Context, parent: ViewGroup): View {
|
||||
return LayoutInflater.from(context).inflate(R.layout.layout_extra_config_checkbox, parent, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(context: Context, view: View, fragment: CustomTabsFragment.TabEditorDialogFragment) {
|
||||
super.onViewCreated(context, view, fragment)
|
||||
val titleView = view.findViewById(android.R.id.title) as TextView
|
||||
val summaryView = view.findViewById(android.R.id.summary) as TextView
|
||||
summaryView.visibility = View.GONE
|
||||
titleView.text = title.createString(context)
|
||||
view.setOnClickListener {
|
||||
val account = fragment.account ?: return@setOnClickListener
|
||||
val intent = Intent(context, TrendsLocationSelectorActivity::class.java)
|
||||
intent.putExtra(EXTRA_ACCOUNT_KEY, account.key)
|
||||
fragment.startExtraConfigurationActivityForResult(this@PlaceExtraConfiguration, intent, 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
when (requestCode) {
|
||||
1 -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class Place(var woeId: Int, var name: String)
|
||||
}
|
|
@ -42,11 +42,6 @@
|
|||
android:summaryOn="@string/read_from_bottom_summary_on"
|
||||
android:title="@string/read_from_bottom"/>
|
||||
|
||||
<org.mariotaku.twidere.preference.TrendsLocationPreference
|
||||
android:key="local_trends_woeid"
|
||||
android:summary="@string/trends_location_summary"
|
||||
android:title="@string/trends_location"/>
|
||||
|
||||
<org.mariotaku.twidere.preference.TranslationDestinationPreference
|
||||
android:key="translation_destination"
|
||||
android:title="@string/translation_destination"/>
|
||||
|
|
Loading…
Reference in New Issue