using separate trends location

This commit is contained in:
Mariotaku Lee 2017-02-02 23:50:30 +08:00
parent 8685437b85
commit 0813eb907a
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
12 changed files with 501 additions and 352 deletions

View File

@ -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";
}

View File

@ -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;
}

View File

@ -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];
}
};
}

View File

@ -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"

View File

@ -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

View File

@ -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();
}
}
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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
}
}

View File

@ -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

View File

@ -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)
}

View File

@ -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"/>