fedilab-Android-App/app/src/main/java/app/fedilab/android/mastodon/activities/HashTagActivity.java

417 lines
19 KiB
Java

package app.fedilab.android.mastodon.activities;
/* Copyright 2022 Thomas Schneider
*
* This file is a part of Fedilab
*
* 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.
*
* Fedilab 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 Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Menu;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList;
import java.util.List;
import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.BuildConfig;
import app.fedilab.android.R;
import app.fedilab.android.activities.MainActivity;
import app.fedilab.android.databinding.ActivityHashtagBinding;
import app.fedilab.android.mastodon.client.entities.api.Filter;
import app.fedilab.android.mastodon.client.entities.api.Status;
import app.fedilab.android.mastodon.client.entities.app.CachedBundle;
import app.fedilab.android.mastodon.client.entities.app.Pinned;
import app.fedilab.android.mastodon.client.entities.app.PinnedTimeline;
import app.fedilab.android.mastodon.client.entities.app.StatusDraft;
import app.fedilab.android.mastodon.client.entities.app.TagTimeline;
import app.fedilab.android.mastodon.client.entities.app.Timeline;
import app.fedilab.android.mastodon.exception.DBException;
import app.fedilab.android.mastodon.helper.Helper;
import app.fedilab.android.mastodon.ui.fragment.timeline.FragmentMastodonTimeline;
import app.fedilab.android.mastodon.viewmodel.mastodon.FiltersVM;
import app.fedilab.android.mastodon.viewmodel.mastodon.ReorderVM;
import app.fedilab.android.mastodon.viewmodel.mastodon.TagVM;
import es.dmoral.toasty.Toasty;
public class HashTagActivity extends BaseActivity {
public static int position;
private String tag;
private String stripTag;
private Boolean pinnedTag;
private Boolean followedTag;
private Boolean mutedTag;
private TagVM tagVM;
private Filter fedilabFilter;
private Filter.KeywordsAttributes keyword;
private PinnedTimeline pinnedTimeline;
private Pinned pinned;
private ActivityHashtagBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityHashtagBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
Bundle args = getIntent().getExtras();
if (args != null) {
long bundleId = args.getLong(Helper.ARG_INTENT_ID, -1);
new CachedBundle(HashTagActivity.this).getBundle(bundleId, Helper.getCurrentAccount(HashTagActivity.this), this::initializeAfterBundle);
} else {
initializeAfterBundle(null);
}
}
private void initializeAfterBundle(Bundle bundle) {
if (bundle != null) {
tag = bundle.getString(Helper.ARG_SEARCH_KEYWORD, null);
}
if (tag == null) {
finish();
return;
}
pinnedTag = null;
followedTag = null;
mutedTag = null;
stripTag = tag.replaceAll("#", "");
setSupportActionBar(binding.toolbar);
ActionBar actionBar = getSupportActionBar();
//Remove title
if (actionBar != null) {
actionBar.setDisplayShowTitleEnabled(false);
}
binding.title.setText(tag);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
tagVM = new ViewModelProvider(HashTagActivity.this).get(TagVM.class);
tagVM.getTag(MainActivity.currentInstance, MainActivity.currentToken, stripTag).observe(this, returnedTag -> {
if (returnedTag != null) {
followedTag = returnedTag.following;
invalidateOptionsMenu();
}
});
ReorderVM reorderVM = new ViewModelProvider(HashTagActivity.this).get(ReorderVM.class);
reorderVM.getAllPinned().observe(HashTagActivity.this, pinned -> {
if (pinned == null) {
pinned = new Pinned();
pinned.pinnedTimelines = new ArrayList<>();
}
this.pinned = pinned;
pinnedTag = false;
if (pinned.pinnedTimelines != null) {
for (PinnedTimeline pinnedTimeline : pinned.pinnedTimelines) {
if (pinnedTimeline.tagTimeline != null) {
if (pinnedTimeline.tagTimeline.name.equalsIgnoreCase(stripTag)) {
this.pinnedTimeline = pinnedTimeline;
pinnedTag = true;
break;
}
}
}
invalidateOptionsMenu();
}
});
if (MainActivity.filterFetched && MainActivity.mainFilters != null) {
mutedTag = false;
for (Filter filter : MainActivity.mainFilters) {
if (filter.title.equalsIgnoreCase(Helper.FEDILAB_MUTED_HASHTAGS)) {
fedilabFilter = filter;
String fetch = tag.startsWith("#") ? tag : "#" + tag;
for (Filter.KeywordsAttributes keywordsAttributes : filter.keywords) {
if (fetch.equalsIgnoreCase(keywordsAttributes.keyword)) {
mutedTag = true;
keyword = keywordsAttributes;
invalidateOptionsMenu();
break;
}
}
}
}
invalidateOptionsMenu();
}
Bundle bundleFragment = new Bundle();
bundleFragment.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.TAG);
bundleFragment.putString(Helper.ARG_SEARCH_KEYWORD, tag);
Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_tags, new FragmentMastodonTimeline(), bundleFragment, null, null);
binding.compose.setOnClickListener(v -> {
Intent intentToot = new Intent(HashTagActivity.this, ComposeActivity.class);
StatusDraft statusDraft = new StatusDraft();
Status status = new Status();
status.text = "#" + stripTag;
List<Status> statuses = new ArrayList<>();
statuses.add(status);
statusDraft.statusDraftList = statuses;
Bundle args = new Bundle();
args.putSerializable(Helper.ARG_STATUS_DRAFT, statusDraft);
new CachedBundle(HashTagActivity.this).insertBundle(args, Helper.getCurrentAccount(HashTagActivity.this), bundleId -> {
Bundle bundleCached = new Bundle();
bundleCached.putLong(Helper.ARG_INTENT_ID, bundleId);
intentToot.putExtras(bundleCached);
startActivity(intentToot);
});
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
} else if (item.getItemId() == R.id.action_add_timeline) {
if (pinnedTag) {
AlertDialog.Builder unpinConfirm = new MaterialAlertDialogBuilder(HashTagActivity.this);
unpinConfirm.setMessage(getString(R.string.unpin_timeline_description));
unpinConfirm.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
unpinConfirm.setPositiveButton(R.string.yes, (dialog, which) -> {
if (pinned == null || pinned.pinnedTimelines == null) {
return;
}
pinned.pinnedTimelines.remove(pinnedTimeline);
try {
new Pinned(HashTagActivity.this).updatePinned(pinned);
} catch (DBException e) {
e.printStackTrace();
}
pinnedTag = false;
invalidateOptionsMenu();
Bundle args = new Bundle();
args.putBoolean(Helper.RECEIVE_REDRAW_TOPBAR, true);
Intent intentBD = new Intent(Helper.BROADCAST_DATA);
new CachedBundle(HashTagActivity.this).insertBundle(args, Helper.getCurrentAccount(HashTagActivity.this), bundleId -> {
Bundle bundle = new Bundle();
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
intentBD.putExtras(bundle);
intentBD.setPackage(BuildConfig.APPLICATION_ID);
sendBroadcast(intentBD);
dialog.dismiss();
});
});
unpinConfirm.show();
} else {
new Thread(() -> {
try {
Pinned pinned = new Pinned(HashTagActivity.this).getPinned(Helper.getCurrentAccount(HashTagActivity.this));
boolean canBeAdded = true;
boolean update = true;
if (pinned == null) {
pinned = new Pinned();
pinned.pinnedTimelines = new ArrayList<>();
update = false;
} else {
for (PinnedTimeline pinnedTimeline : pinned.pinnedTimelines) {
if (pinnedTimeline.type == Timeline.TimeLineEnum.TAG) {
if (pinnedTimeline.tagTimeline.name.compareTo(stripTag.trim()) == 0) {
canBeAdded = false;
}
}
}
}
if (!canBeAdded) {
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> Toasty.warning(HashTagActivity.this, getString(R.string.tags_already_stored), Toasty.LENGTH_SHORT).show();
mainHandler.post(myRunnable);
return;
}
pinnedTimeline = new PinnedTimeline();
pinnedTimeline.type = Timeline.TimeLineEnum.TAG;
pinnedTimeline.position = pinned.pinnedTimelines.size();
pinnedTimeline.displayed = true;
TagTimeline tagTimeline = new TagTimeline();
tagTimeline.name = stripTag.trim();
tagTimeline.isNSFW = false;
tagTimeline.isART = false;
tagTimeline.any = new ArrayList<>();
tagTimeline.any.add(stripTag.trim());
pinnedTimeline.tagTimeline = tagTimeline;
pinned.pinnedTimelines.add(pinnedTimeline);
if (pinned.instance == null || pinned.user_id == null) {
pinned.instance = MainActivity.currentInstance;
pinned.user_id = MainActivity.currentUserID;
}
if (update) {
new Pinned(HashTagActivity.this).updatePinned(pinned);
} else {
new Pinned(HashTagActivity.this).insertPinned(pinned);
}
Bundle args = new Bundle();
args.putBoolean(Helper.RECEIVE_REDRAW_TOPBAR, true);
Intent intentBD = new Intent(Helper.BROADCAST_DATA);
new CachedBundle(HashTagActivity.this).insertBundle(args, Helper.getCurrentAccount(HashTagActivity.this), bundleId -> {
Bundle bundle = new Bundle();
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
intentBD.putExtras(bundle);
intentBD.setPackage(BuildConfig.APPLICATION_ID);
sendBroadcast(intentBD);
});
pinnedTag = true;
invalidateOptionsMenu();
} catch (DBException e) {
e.printStackTrace();
}
}).start();
}
} else if (item.getItemId() == R.id.action_follow_tag) {
if (!followedTag) {
tagVM.follow(MainActivity.currentInstance, MainActivity.currentToken, stripTag).observe(this, returnedTag -> {
if (returnedTag != null) {
followedTag = returnedTag.following;
invalidateOptionsMenu();
}
});
} else {
tagVM.unfollow(MainActivity.currentInstance, MainActivity.currentToken, stripTag).observe(this, returnedTag -> {
if (returnedTag != null) {
followedTag = returnedTag.following;
invalidateOptionsMenu();
}
});
}
} else if (item.getItemId() == R.id.action_mute) {
if (!mutedTag) {
if (MainActivity.mainFilters == null || fedilabFilter == null) {
MainActivity.mainFilters = new ArrayList<>();
Filter.FilterParams filterParams = new Filter.FilterParams();
filterParams.title = Helper.FEDILAB_MUTED_HASHTAGS;
filterParams.filter_action = "hide";
filterParams.context = new ArrayList<>();
filterParams.context.add("home");
filterParams.context.add("public");
filterParams.context.add("thread");
filterParams.context.add("account");
FiltersVM filtersVM = new ViewModelProvider(HashTagActivity.this).get(FiltersVM.class);
filtersVM.addFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filterParams)
.observe(HashTagActivity.this, filter -> {
if (filter != null) {
MainActivity.mainFilters.add(filter);
mutedTag = false;
fedilabFilter = filter;
muteTags();
invalidateOptionsMenu();
}
});
} else {
muteTags();
}
} else {
unmuteTags();
}
}
return super.onOptionsItemSelected(item);
}
private void unmuteTags() {
String search = tag.startsWith("#") ? tag : "#" + tag;
for (Filter.KeywordsAttributes keywordsAttributes : fedilabFilter.keywords) {
if (search.equalsIgnoreCase(keywordsAttributes.keyword)) {
keyword = keywordsAttributes;
break;
}
}
if (keyword != null && keyword.id != null) {
FiltersVM filtersVM = new ViewModelProvider(HashTagActivity.this).get(FiltersVM.class);
filtersVM.removeKeyword(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, keyword.id);
fedilabFilter.keywords.remove(keyword);
mutedTag = false;
invalidateOptionsMenu();
}
}
private void muteTags() {
Filter.FilterParams filterParams = new Filter.FilterParams();
filterParams.id = fedilabFilter.id;
filterParams.keywords = new ArrayList<>();
Filter.KeywordsParams keywordsParams = new Filter.KeywordsParams();
keywordsParams.whole_word = true;
keywordsParams.keyword = tag.startsWith("#") ? tag : "#" + tag;
filterParams.keywords.add(keywordsParams);
filterParams.context = fedilabFilter.context;
FiltersVM filtersVM = new ViewModelProvider(HashTagActivity.this).get(FiltersVM.class);
filtersVM.editFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filterParams)
.observe(HashTagActivity.this, filter -> {
fedilabFilter = filter;
mutedTag = true;
invalidateOptionsMenu();
});
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
getMenuInflater().inflate(R.menu.menu_hashtag, menu);
MenuItem pin = menu.findItem(R.id.action_add_timeline);
MenuItem follow = menu.findItem(R.id.action_follow_tag);
MenuItem mute = menu.findItem(R.id.action_mute);
if (pinnedTag != null) {
pin.setVisible(true);
if (pinnedTag) {
pin.setIcon(R.drawable.tag_pin_off);
pin.setTitle(getString(R.string.unpin_tag));
} else {
pin.setTitle(getString(R.string.pin_tag));
pin.setIcon(R.drawable.tag_pin);
}
} else {
pin.setVisible(false);
}
if (followedTag != null) {
follow.setVisible(true);
if (followedTag) {
follow.setTitle(getString(R.string.unfollow_tag));
follow.setIcon(R.drawable.tag_unfollow);
} else {
follow.setTitle(getString(R.string.follow_tag));
follow.setIcon(R.drawable.tag_follow);
}
} else {
follow.setVisible(false);
}
if (mutedTag != null) {
mute.setVisible(true);
if (mutedTag) {
mute.setTitle(getString(R.string.unmute_tag_action));
mute.setIcon(R.drawable.tag_unmuted);
} else {
mute.setTitle(getString(R.string.mute_tag_action));
mute.setIcon(R.drawable.tag_muted);
}
} else {
mute.setVisible(false);
}
return super.onCreateOptionsMenu(menu);
}
}