parent
e3520df57e
commit
c4e23b0fe6
|
@ -0,0 +1,11 @@
|
||||||
|
package org.joinmastodon.android.events;
|
||||||
|
|
||||||
|
public class HashtagUpdatedEvent {
|
||||||
|
public final String name;
|
||||||
|
public final boolean following;
|
||||||
|
|
||||||
|
public HashtagUpdatedEvent(String name, boolean following) {
|
||||||
|
this.name = name;
|
||||||
|
this.following = following;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package org.joinmastodon.android.events;
|
||||||
|
|
||||||
|
public class ListDeletedEvent {
|
||||||
|
public final String id;
|
||||||
|
|
||||||
|
public ListDeletedEvent(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package org.joinmastodon.android.events;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.model.ListTimeline;
|
||||||
|
|
||||||
|
public class ListUpdatedCreatedEvent {
|
||||||
|
public final String id;
|
||||||
|
public final String title;
|
||||||
|
public final ListTimeline.RepliesPolicy repliesPolicy;
|
||||||
|
|
||||||
|
public ListUpdatedCreatedEvent(String id, String title, ListTimeline.RepliesPolicy repliesPolicy) {
|
||||||
|
this.id = id;
|
||||||
|
this.title = title;
|
||||||
|
this.repliesPolicy = repliesPolicy;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,10 +11,12 @@ import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.E;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.requests.tags.GetHashtag;
|
import org.joinmastodon.android.api.requests.tags.GetHashtag;
|
||||||
import org.joinmastodon.android.api.requests.tags.SetHashtagFollowed;
|
import org.joinmastodon.android.api.requests.tags.SetHashtagFollowed;
|
||||||
import org.joinmastodon.android.api.requests.timelines.GetHashtagTimeline;
|
import org.joinmastodon.android.api.requests.timelines.GetHashtagTimeline;
|
||||||
|
import org.joinmastodon.android.events.HashtagUpdatedEvent;
|
||||||
import org.joinmastodon.android.model.Hashtag;
|
import org.joinmastodon.android.model.Hashtag;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.model.TimelineDefinition;
|
import org.joinmastodon.android.model.TimelineDefinition;
|
||||||
|
@ -55,6 +57,7 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment {
|
||||||
this.following = newFollowing;
|
this.following = newFollowing;
|
||||||
followButton.setTitle(getString(newFollowing ? R.string.unfollow_user : R.string.follow_user, "#" + hashtag));
|
followButton.setTitle(getString(newFollowing ? R.string.unfollow_user : R.string.follow_user, "#" + hashtag));
|
||||||
followButton.setIcon(newFollowing ? R.drawable.ic_fluent_person_delete_24_filled : R.drawable.ic_fluent_person_add_24_regular);
|
followButton.setIcon(newFollowing ? R.drawable.ic_fluent_person_delete_24_filled : R.drawable.ic_fluent_person_add_24_regular);
|
||||||
|
E.post(new HashtagUpdatedEvent(hashtag, following));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -39,6 +39,9 @@ import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.requests.announcements.GetAnnouncements;
|
import org.joinmastodon.android.api.requests.announcements.GetAnnouncements;
|
||||||
import org.joinmastodon.android.api.requests.lists.GetLists;
|
import org.joinmastodon.android.api.requests.lists.GetLists;
|
||||||
import org.joinmastodon.android.api.requests.tags.GetFollowedHashtags;
|
import org.joinmastodon.android.api.requests.tags.GetFollowedHashtags;
|
||||||
|
import org.joinmastodon.android.events.HashtagUpdatedEvent;
|
||||||
|
import org.joinmastodon.android.events.ListDeletedEvent;
|
||||||
|
import org.joinmastodon.android.events.ListUpdatedCreatedEvent;
|
||||||
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
|
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
|
||||||
import org.joinmastodon.android.model.Announcement;
|
import org.joinmastodon.android.model.Announcement;
|
||||||
import org.joinmastodon.android.model.Hashtag;
|
import org.joinmastodon.android.model.Hashtag;
|
||||||
|
@ -52,6 +55,9 @@ import org.joinmastodon.android.updater.GithubSelfUpdater;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import me.grishka.appkit.Nav;
|
import me.grishka.appkit.Nav;
|
||||||
import me.grishka.appkit.api.Callback;
|
import me.grishka.appkit.api.Callback;
|
||||||
|
@ -93,6 +99,7 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
E.register(this);
|
||||||
accountID = getArguments().getString("account");
|
accountID = getArguments().getString("account");
|
||||||
timelineDefinitions = GlobalUserPreferences.pinnedTimelines.getOrDefault(accountID, TimelineDefinition.DEFAULT_TIMELINES);
|
timelineDefinitions = GlobalUserPreferences.pinnedTimelines.getOrDefault(accountID, TimelineDefinition.DEFAULT_TIMELINES);
|
||||||
assert timelineDefinitions != null;
|
assert timelineDefinitions != null;
|
||||||
|
@ -212,7 +219,6 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GithubSelfUpdater.needSelfUpdating()){
|
if(GithubSelfUpdater.needSelfUpdating()){
|
||||||
E.register(this);
|
|
||||||
updateUpdateState(GithubSelfUpdater.getInstance().getState());
|
updateUpdateState(GithubSelfUpdater.getInstance().getState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,6 +578,50 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
|
||||||
outState.putInt("selectedTab", pager.getCurrentItem());
|
outState.putInt("selectedTab", pager.getCurrentItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onHashtagUpdatedEvent(HashtagUpdatedEvent event) {
|
||||||
|
handleListEvent(hashtagsItems, h -> h.name.equalsIgnoreCase(event.name), event.following, () -> {
|
||||||
|
Hashtag hashtag = new Hashtag();
|
||||||
|
hashtag.name = event.name;
|
||||||
|
hashtag.following = true;
|
||||||
|
return hashtag;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onListDeletedEvent(ListDeletedEvent event) {
|
||||||
|
handleListEvent(listItems, l -> l.id.equals(event.id), false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onListUpdatedCreatedEvent(ListUpdatedCreatedEvent event) {
|
||||||
|
handleListEvent(listItems, l -> l.id.equals(event.id), true, () -> {
|
||||||
|
ListTimeline list = new ListTimeline();
|
||||||
|
list.id = event.id;
|
||||||
|
list.title = event.title;
|
||||||
|
list.repliesPolicy = event.repliesPolicy;
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> void handleListEvent(
|
||||||
|
Map<Integer, T> existingThings,
|
||||||
|
Predicate<T> matchExisting,
|
||||||
|
boolean shouldBeInList,
|
||||||
|
Supplier<T> makeNewThing
|
||||||
|
) {
|
||||||
|
Optional<Map.Entry<Integer, T>> existingThing = existingThings.entrySet().stream()
|
||||||
|
.filter(e -> matchExisting.test(e.getValue())).findFirst();
|
||||||
|
if (shouldBeInList) {
|
||||||
|
existingThings.put(existingThing.isPresent()
|
||||||
|
? existingThing.get().getKey() : View.generateViewId(), makeNewThing.get());
|
||||||
|
createOptionsMenu();
|
||||||
|
} else if (existingThing.isPresent() && !shouldBeInList) {
|
||||||
|
existingThings.remove(existingThing.get().getKey());
|
||||||
|
createOptionsMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class HomePagerAdapter extends RecyclerView.Adapter<SimpleViewHolder> {
|
private class HomePagerAdapter extends RecyclerView.Adapter<SimpleViewHolder> {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -11,10 +11,13 @@ import android.widget.ImageButton;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.E;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.requests.lists.GetList;
|
import org.joinmastodon.android.api.requests.lists.GetList;
|
||||||
import org.joinmastodon.android.api.requests.lists.UpdateList;
|
import org.joinmastodon.android.api.requests.lists.UpdateList;
|
||||||
import org.joinmastodon.android.api.requests.timelines.GetListTimeline;
|
import org.joinmastodon.android.api.requests.timelines.GetListTimeline;
|
||||||
|
import org.joinmastodon.android.events.ListDeletedEvent;
|
||||||
|
import org.joinmastodon.android.events.ListUpdatedCreatedEvent;
|
||||||
import org.joinmastodon.android.model.ListTimeline;
|
import org.joinmastodon.android.model.ListTimeline;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.model.TimelineDefinition;
|
import org.joinmastodon.android.model.TimelineDefinition;
|
||||||
|
@ -87,33 +90,30 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
|
||||||
.setTitle(R.string.sk_edit_list_title)
|
.setTitle(R.string.sk_edit_list_title)
|
||||||
.setIcon(R.drawable.ic_fluent_people_list_28_regular)
|
.setIcon(R.drawable.ic_fluent_people_list_28_regular)
|
||||||
.setView(editor)
|
.setView(editor)
|
||||||
.setPositiveButton(R.string.save, (d, which) ->
|
.setPositiveButton(R.string.save, (d, which) -> {
|
||||||
new UpdateList(listID, editor.getTitle(), editor.getRepliesPolicy()).setCallback(new Callback<>() {
|
String newTitle = editor.getTitle().trim();
|
||||||
@Override
|
setTitle(newTitle);
|
||||||
public void onSuccess(ListTimeline list) {
|
new UpdateList(listID, newTitle, editor.getRepliesPolicy()).setCallback(new Callback<>() {
|
||||||
setTitle(list.title);
|
@Override
|
||||||
listTitle = list.title;
|
public void onSuccess(ListTimeline list) {
|
||||||
repliesPolicy = list.repliesPolicy;
|
setTitle(list.title);
|
||||||
Bundle result = new Bundle();
|
listTitle = list.title;
|
||||||
result.putString("listID", listID);
|
repliesPolicy = list.repliesPolicy;
|
||||||
result.putString("listTitle", listTitle);
|
E.post(new ListUpdatedCreatedEvent(listID, listTitle, repliesPolicy));
|
||||||
if (repliesPolicy != null) result.putInt("repliesPolicy", repliesPolicy.ordinal());
|
}
|
||||||
setResult(true, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(ErrorResponse error) {
|
public void onError(ErrorResponse error) {
|
||||||
error.showToast(getContext());
|
setTitle(listTitle);
|
||||||
}
|
error.showToast(getContext());
|
||||||
}).exec(accountID))
|
}
|
||||||
|
}).exec(accountID);
|
||||||
|
})
|
||||||
.setNegativeButton(R.string.cancel, (d, which) -> {})
|
.setNegativeButton(R.string.cancel, (d, which) -> {})
|
||||||
.show();
|
.show();
|
||||||
} else if (item.getItemId() == R.id.delete) {
|
} else if (item.getItemId() == R.id.delete) {
|
||||||
UiUtils.confirmDeleteList(getActivity(), accountID, listID, listTitle, () -> {
|
UiUtils.confirmDeleteList(getActivity(), accountID, listID, listTitle, () -> {
|
||||||
Bundle result = new Bundle();
|
E.post(new ListDeletedEvent(listID));
|
||||||
result.putBoolean("deleted", true);
|
|
||||||
result.putString("listID", listID);
|
|
||||||
setResult(true, result);
|
|
||||||
Nav.finish(this);
|
Nav.finish(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,17 @@ import android.widget.TextView;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.E;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||||
import org.joinmastodon.android.api.requests.lists.AddAccountsToList;
|
import org.joinmastodon.android.api.requests.lists.AddAccountsToList;
|
||||||
import org.joinmastodon.android.api.requests.lists.CreateList;
|
import org.joinmastodon.android.api.requests.lists.CreateList;
|
||||||
import org.joinmastodon.android.api.requests.lists.GetLists;
|
import org.joinmastodon.android.api.requests.lists.GetLists;
|
||||||
import org.joinmastodon.android.api.requests.lists.RemoveAccountsFromList;
|
import org.joinmastodon.android.api.requests.lists.RemoveAccountsFromList;
|
||||||
|
import org.joinmastodon.android.events.ListDeletedEvent;
|
||||||
|
import org.joinmastodon.android.events.ListUpdatedCreatedEvent;
|
||||||
import org.joinmastodon.android.model.ListTimeline;
|
import org.joinmastodon.android.model.ListTimeline;
|
||||||
import org.joinmastodon.android.ui.DividerItemDecoration;
|
import org.joinmastodon.android.ui.DividerItemDecoration;
|
||||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
|
@ -37,8 +42,6 @@ import me.grishka.appkit.utils.BindableViewHolder;
|
||||||
import me.grishka.appkit.views.UsableRecyclerView;
|
import me.grishka.appkit.views.UsableRecyclerView;
|
||||||
|
|
||||||
public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> implements ScrollableToTop {
|
public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> implements ScrollableToTop {
|
||||||
private static final int LIST_CHANGED_RESULT = 987;
|
|
||||||
|
|
||||||
private String accountId;
|
private String accountId;
|
||||||
private String profileAccountId;
|
private String profileAccountId;
|
||||||
private final HashMap<String, Boolean> userInListBefore = new HashMap<>();
|
private final HashMap<String, Boolean> userInListBefore = new HashMap<>();
|
||||||
|
@ -55,6 +58,7 @@ public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> im
|
||||||
Bundle args=getArguments();
|
Bundle args=getArguments();
|
||||||
accountId=args.getString("account");
|
accountId=args.getString("account");
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
E.register(this);
|
||||||
|
|
||||||
if(args.containsKey("profileAccount")){
|
if(args.containsKey("profileAccount")){
|
||||||
profileAccountId=args.getString("profileAccount");
|
profileAccountId=args.getString("profileAccount");
|
||||||
|
@ -98,6 +102,7 @@ public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> im
|
||||||
saveListMembership(list.id, true);
|
saveListMembership(list.id, true);
|
||||||
data.add(0, list);
|
data.add(0, list);
|
||||||
adapter.notifyItemRangeInserted(0, 1);
|
adapter.notifyItemRangeInserted(0, 1);
|
||||||
|
E.post(new ListUpdatedCreatedEvent(list.id, list.title, list.repliesPolicy));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -116,9 +121,14 @@ public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> im
|
||||||
userInList.put(listId, isMember);
|
userInList.put(listId, isMember);
|
||||||
List<String> accountIdList = Collections.singletonList(profileAccountId);
|
List<String> accountIdList = Collections.singletonList(profileAccountId);
|
||||||
MastodonAPIRequest<Object> req = isMember ? new AddAccountsToList(listId, accountIdList) : new RemoveAccountsFromList(listId, accountIdList);
|
MastodonAPIRequest<Object> req = isMember ? new AddAccountsToList(listId, accountIdList) : new RemoveAccountsFromList(listId, accountIdList);
|
||||||
req.setCallback(new SimpleCallback<>(this) {
|
req.setCallback(new Callback<>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Object o) {}
|
public void onSuccess(Object o) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(ErrorResponse error) {
|
||||||
|
error.showToast(getContext());
|
||||||
|
}
|
||||||
}).exec(accountId);
|
}).exec(accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,29 +164,31 @@ public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> im
|
||||||
.exec(accountId);
|
.exec(accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Subscribe
|
||||||
public void onFragmentResult(int reqCode, boolean listChanged, Bundle result){
|
public void onListDeletedEvent(ListDeletedEvent event) {
|
||||||
if (reqCode == LIST_CHANGED_RESULT && listChanged) {
|
for (int i = 0; i < data.size(); i++) {
|
||||||
String listID = result.getString("listID");
|
ListTimeline item = data.get(i);
|
||||||
for (int i = 0; i < data.size(); i++) {
|
if (item.id.equals(event.id)) {
|
||||||
ListTimeline item = data.get(i);
|
data.remove(i);
|
||||||
if (item.id.equals(listID)) {
|
adapter.notifyItemRemoved(i);
|
||||||
if (result.getBoolean("deleted")) {
|
break;
|
||||||
data.remove(i);
|
}
|
||||||
adapter.notifyItemRemoved(i);
|
}
|
||||||
} else {
|
|
||||||
item.title = result.getString("listTitle", item.title);
|
|
||||||
if (result.containsKey("repliesPolicy")) {
|
|
||||||
item.repliesPolicy = ListTimeline.RepliesPolicy.values()[result.getInt("repliesPolicy")];
|
|
||||||
}
|
|
||||||
adapter.notifyItemChanged(i);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onListUpdatedCreatedEvent(ListUpdatedCreatedEvent event) {
|
||||||
|
for (int i = 0; i < data.size(); i++) {
|
||||||
|
ListTimeline item = data.get(i);
|
||||||
|
if (item.id.equals(event.id)) {
|
||||||
|
item.title = event.title;
|
||||||
|
item.repliesPolicy = event.repliesPolicy;
|
||||||
|
adapter.notifyItemChanged(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RecyclerView.Adapter<ListViewHolder> getAdapter() {
|
protected RecyclerView.Adapter<ListViewHolder> getAdapter() {
|
||||||
return adapter = new ListsAdapter();
|
return adapter = new ListsAdapter();
|
||||||
|
@ -240,7 +252,7 @@ public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> im
|
||||||
args.putString("listID", item.id);
|
args.putString("listID", item.id);
|
||||||
args.putString("listTitle", item.title);
|
args.putString("listTitle", item.title);
|
||||||
if (item.repliesPolicy != null) args.putInt("repliesPolicy", item.repliesPolicy.ordinal());
|
if (item.repliesPolicy != null) args.putInt("repliesPolicy", item.repliesPolicy.ordinal());
|
||||||
Nav.goForResult(getActivity(), ListTimelineFragment.class, args, LIST_CHANGED_RESULT, ListTimelinesFragment.this);
|
Nav.go(getActivity(), ListTimelineFragment.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue