summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/src/main/AndroidManifest.xml5
-rw-r--r--app/src/main/java/app/fedilab/android/BaseMainActivity.java4
-rw-r--r--app/src/main/java/app/fedilab/android/activities/FollowedTagActivity.java202
-rw-r--r--app/src/main/java/app/fedilab/android/activities/HashTagActivity.java51
-rw-r--r--app/src/main/java/app/fedilab/android/client/endpoints/MastodonTagService.java13
-rw-r--r--app/src/main/java/app/fedilab/android/ui/drawer/FollowedTagAdapter.java79
-rw-r--r--app/src/main/java/app/fedilab/android/viewmodel/mastodon/ReorderVM.java19
-rw-r--r--app/src/main/java/app/fedilab/android/viewmodel/mastodon/TagVM.java43
-rw-r--r--app/src/main/res/drawable/ic_baseline_post_add_24.xml22
-rw-r--r--app/src/main/res/drawable/ic_baseline_tag_24.xml10
-rw-r--r--app/src/main/res/layout/activity_followed_tags.xml33
-rw-r--r--app/src/main/res/layout/popup_add_followed_tagt.xml17
-rw-r--r--app/src/main/res/menu/activity_main_drawer.xml4
-rw-r--r--app/src/main/res/menu/menu_followed_tag.xml9
-rw-r--r--app/src/main/res/menu/menu_hashtag.xml14
-rw-r--r--app/src/main/res/menu/menu_main_followed_tag.xml9
-rw-r--r--app/src/main/res/values/strings.xml9
17 files changed, 527 insertions, 16 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a34f97d59..1b449cdeb 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -252,6 +252,11 @@
android:label="@string/action_lists"
android:theme="@style/AppThemeBar" />
<activity
+ android:name=".activities.FollowedTagActivity"
+ android:configChanges="keyboardHidden|orientation|screenSize"
+ android:label="@string/followed_tags"
+ android:theme="@style/AppThemeBar" />
+ <activity
android:name=".activities.SettingsActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/settings"
diff --git a/app/src/main/java/app/fedilab/android/BaseMainActivity.java b/app/src/main/java/app/fedilab/android/BaseMainActivity.java
index 08ff2d3c1..d45451134 100644
--- a/app/src/main/java/app/fedilab/android/BaseMainActivity.java
+++ b/app/src/main/java/app/fedilab/android/BaseMainActivity.java
@@ -103,6 +103,7 @@ import app.fedilab.android.activities.ContextActivity;
import app.fedilab.android.activities.DraftActivity;
import app.fedilab.android.activities.FilterActivity;
import app.fedilab.android.activities.FollowRequestActivity;
+import app.fedilab.android.activities.FollowedTagActivity;
import app.fedilab.android.activities.InstanceActivity;
import app.fedilab.android.activities.InstanceHealthActivity;
import app.fedilab.android.activities.LoginActivity;
@@ -359,6 +360,9 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
} else if (id == R.id.nav_list) {
Intent intent = new Intent(this, MastodonListActivity.class);
startActivity(intent);
+ } else if (id == R.id.nav_followed_tags) {
+ Intent intent = new Intent(this, FollowedTagActivity.class);
+ startActivity(intent);
} else if (id == R.id.nav_settings) {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
diff --git a/app/src/main/java/app/fedilab/android/activities/FollowedTagActivity.java b/app/src/main/java/app/fedilab/android/activities/FollowedTagActivity.java
new file mode 100644
index 000000000..076330025
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/activities/FollowedTagActivity.java
@@ -0,0 +1,202 @@
+package app.fedilab.android.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.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.text.InputFilter;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+import java.util.ArrayList;
+
+import app.fedilab.android.BaseMainActivity;
+import app.fedilab.android.R;
+import app.fedilab.android.client.entities.api.Tag;
+import app.fedilab.android.client.entities.app.Timeline;
+import app.fedilab.android.databinding.ActivityFollowedTagsBinding;
+import app.fedilab.android.databinding.PopupAddFollowedTagtBinding;
+import app.fedilab.android.helper.Helper;
+import app.fedilab.android.helper.ThemeHelper;
+import app.fedilab.android.ui.drawer.FollowedTagAdapter;
+import app.fedilab.android.ui.fragment.timeline.FragmentMastodonTimeline;
+import app.fedilab.android.viewmodel.mastodon.TagVM;
+import es.dmoral.toasty.Toasty;
+
+
+public class FollowedTagActivity extends BaseActivity implements FollowedTagAdapter.ActionOnTag {
+
+
+ private ActivityFollowedTagsBinding binding;
+ private boolean canGoBack;
+ private TagVM tagVM;
+ private Tag tag;
+ private ArrayList<Tag> tagList;
+ private FollowedTagAdapter followedTagAdapter;
+ private FragmentMastodonTimeline fragmentMastodonTimeline;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ThemeHelper.applyThemeBar(this);
+ binding = ActivityFollowedTagsBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+ canGoBack = false;
+ if (getSupportActionBar() != null) {
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayShowHomeEnabled(true);
+ getSupportActionBar().setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
+ }
+ tagVM = new ViewModelProvider(FollowedTagActivity.this).get(TagVM.class);
+ tagVM.followedTags(BaseMainActivity.currentInstance, BaseMainActivity.currentToken)
+ .observe(FollowedTagActivity.this, tags -> {
+ if (tags != null && tags.tags != null && tags.tags.size() > 0) {
+ tagList = new ArrayList<>(tags.tags);
+ followedTagAdapter = new FollowedTagAdapter(tagList);
+ followedTagAdapter.actionOnTag = this;
+ binding.notContent.setVisibility(View.GONE);
+ binding.recyclerView.setAdapter(followedTagAdapter);
+ binding.recyclerView.setLayoutManager(new LinearLayoutManager(FollowedTagActivity.this));
+ } else {
+ binding.notContent.setVisibility(View.VISIBLE);
+ }
+ });
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ } else if (item.getItemId() == R.id.action_unfollow && tag != null) {
+ AlertDialog.Builder alt_bld = new AlertDialog.Builder(FollowedTagActivity.this, Helper.dialogStyle());
+ alt_bld.setTitle(R.string.action_unfollow_tag);
+ alt_bld.setMessage(R.string.action_unfollow_tag_confirm);
+ alt_bld.setPositiveButton(R.string.unfollow, (dialog, id) -> {
+ tagVM.unfollow(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, tag.name);
+ int position = 0;
+ for (Tag tagTmp : tagList) {
+ if (tagTmp.name.equalsIgnoreCase(tag.name)) {
+ break;
+ }
+ position++;
+ }
+ tagList.remove(position);
+ followedTagAdapter.notifyItemRemoved(position);
+ ThemeHelper.slideViewsToRight(binding.fragmentContainer, binding.recyclerView, () -> {
+ canGoBack = false;
+ if (fragmentMastodonTimeline != null) {
+ fragmentMastodonTimeline.onDestroyView();
+ }
+ invalidateOptionsMenu();
+ setTitle(R.string.action_lists);
+ });
+ if (tagList.size() == 0) {
+ binding.notContent.setVisibility(View.VISIBLE);
+ } else {
+ binding.notContent.setVisibility(View.GONE);
+ }
+ });
+ alt_bld.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
+ AlertDialog alert = alt_bld.create();
+ alert.show();
+ } else if (item.getItemId() == R.id.action_follow_tag) {
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(FollowedTagActivity.this, Helper.dialogStyle());
+ PopupAddFollowedTagtBinding popupAddFollowedTagtBinding = PopupAddFollowedTagtBinding.inflate(getLayoutInflater());
+ dialogBuilder.setView(popupAddFollowedTagtBinding.getRoot());
+ popupAddFollowedTagtBinding.addTag.setFilters(new InputFilter[]{new InputFilter.LengthFilter(255)});
+ dialogBuilder.setPositiveButton(R.string.validate, (dialog, id) -> {
+ if (popupAddFollowedTagtBinding.addTag.getText() != null && popupAddFollowedTagtBinding.addTag.getText().toString().trim().length() > 0) {
+ tagVM.follow(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, popupAddFollowedTagtBinding.addTag.getText().toString().trim())
+ .observe(FollowedTagActivity.this, newTag -> {
+ if (tagList == null) {
+ tagList = new ArrayList<>();
+ }
+ if (newTag != null && followedTagAdapter != null) {
+ tagList.add(0, newTag);
+ followedTagAdapter.notifyItemInserted(0);
+ } else {
+ Toasty.error(FollowedTagActivity.this, getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
+ }
+ });
+ dialog.dismiss();
+ } else {
+ popupAddFollowedTagtBinding.addTag.setError(getString(R.string.not_valid_tag_name));
+ }
+
+ });
+ dialogBuilder.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss());
+ dialogBuilder.create().show();
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(@NonNull Menu menu) {
+ if (!canGoBack) {
+ getMenuInflater().inflate(R.menu.menu_main_followed_tag, menu);
+ } else {
+ getMenuInflater().inflate(R.menu.menu_followed_tag, menu);
+ }
+ return true;
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (canGoBack) {
+ canGoBack = false;
+ ThemeHelper.slideViewsToRight(binding.fragmentContainer, binding.recyclerView, () -> {
+ if (fragmentMastodonTimeline != null) {
+ fragmentMastodonTimeline.onDestroyView();
+ }
+ });
+ setTitle(R.string.action_lists);
+ invalidateOptionsMenu();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
+ @Override
+ public void click(Tag tag) {
+ this.tag = tag;
+ canGoBack = true;
+ ThemeHelper.slideViewsToLeft(binding.recyclerView, binding.fragmentContainer, () -> {
+ fragmentMastodonTimeline = new FragmentMastodonTimeline();
+ Bundle bundle = new Bundle();
+ bundle.putSerializable(Helper.ARG_SEARCH_KEYWORD, tag.name);
+ bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.TAG);
+ setTitle(tag.name);
+ fragmentMastodonTimeline.setArguments(bundle);
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ FragmentTransaction fragmentTransaction =
+ fragmentManager.beginTransaction();
+ fragmentTransaction.replace(R.id.fragment_container, fragmentMastodonTimeline);
+ fragmentTransaction.commit();
+ invalidateOptionsMenu();
+ });
+ }
+}
diff --git a/app/src/main/java/app/fedilab/android/activities/HashTagActivity.java b/app/src/main/java/app/fedilab/android/activities/HashTagActivity.java
index 7e7fdb905..82caadc74 100644
--- a/app/src/main/java/app/fedilab/android/activities/HashTagActivity.java
+++ b/app/src/main/java/app/fedilab/android/activities/HashTagActivity.java
@@ -28,6 +28,7 @@ import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.core.content.ContextCompat;
+import androidx.lifecycle.ViewModelProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import java.util.ArrayList;
@@ -45,6 +46,8 @@ import app.fedilab.android.exception.DBException;
import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.ThemeHelper;
import app.fedilab.android.ui.fragment.timeline.FragmentMastodonTimeline;
+import app.fedilab.android.viewmodel.mastodon.ReorderVM;
+import app.fedilab.android.viewmodel.mastodon.TagVM;
import es.dmoral.toasty.Toasty;
@@ -53,6 +56,9 @@ public class HashTagActivity extends BaseActivity {
public static int position;
private String tag;
+ private boolean pinnedTag;
+ private boolean followedTag;
+ private TagVM tagVM;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -67,7 +73,8 @@ public class HashTagActivity extends BaseActivity {
}
if (tag == null)
finish();
-
+ pinnedTag = false;
+ followedTag = false;
setSupportActionBar(binding.toolbar);
ActionBar actionBar = getSupportActionBar();
//Remove title
@@ -81,6 +88,29 @@ public class HashTagActivity extends BaseActivity {
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
+ tagVM = new ViewModelProvider(HashTagActivity.this).get(TagVM.class);
+ tagVM.getTag(MainActivity.currentInstance, MainActivity.currentToken, tag).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) {
+ if (pinned.pinnedTimelines != null) {
+ for (PinnedTimeline pinnedTimeline : pinned.pinnedTimelines) {
+ if (pinnedTimeline.tagTimeline != null) {
+ if (pinnedTimeline.tagTimeline.name.equalsIgnoreCase(tag)) {
+ pinnedTag = true;
+ invalidateOptionsMenu();
+ }
+ }
+ }
+ }
+ }
+ });
+
Bundle bundle = new Bundle();
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.TAG);
bundle.putString(Helper.ARG_SEARCH_KEYWORD, tag);
@@ -151,10 +181,19 @@ public class HashTagActivity extends BaseActivity {
Intent intentBD = new Intent(Helper.BROADCAST_DATA);
intentBD.putExtras(b);
LocalBroadcastManager.getInstance(HashTagActivity.this).sendBroadcast(intentBD);
+ pinnedTag = true;
+ invalidateOptionsMenu();
} catch (DBException e) {
e.printStackTrace();
}
}).start();
+ } else if (item.getItemId() == R.id.action_follow_tag) {
+ tagVM.follow(MainActivity.currentInstance, MainActivity.currentToken, tag).observe(this, returnedTag -> {
+ if (returnedTag != null) {
+ followedTag = returnedTag.following;
+ invalidateOptionsMenu();
+ }
+ });
}
return super.onOptionsItemSelected(item);
@@ -163,7 +202,15 @@ public class HashTagActivity extends BaseActivity {
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
- getMenuInflater().inflate(R.menu.menu_reorder, 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);
+ if (pinnedTag && pin != null) {
+ pin.setVisible(false);
+ }
+ if (followedTag && follow != null) {
+ follow.setVisible(false);
+ }
return super.onCreateOptionsMenu(menu);
}
diff --git a/app/src/main/java/app/fedilab/android/client/endpoints/MastodonTagService.java b/app/src/main/java/app/fedilab/android/client/endpoints/MastodonTagService.java
index 351e379ac..a3f6e4669 100644
--- a/app/src/main/java/app/fedilab/android/client/endpoints/MastodonTagService.java
+++ b/app/src/main/java/app/fedilab/android/client/endpoints/MastodonTagService.java
@@ -23,18 +23,21 @@ import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.POST;
import retrofit2.http.Path;
-import retrofit2.http.Query;
public interface MastodonTagService {
//Get followed tags
@GET("followed_tags")
Call<List<Tag>> getFollowedTags(
+ @Header("Authorization") String token
+ );
+
+
+ //Get followed tags
+ @GET("tags/{name}")
+ Call<Tag> getTag(
@Header("Authorization") String token,
- @Query("max_id") String max_id,
- @Query("since_id") String since_id,
- @Query("min_id") String min_id,
- @Query("limit") int limit
+ @Path("name") String name
);
//Follow tag
diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/FollowedTagAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/FollowedTagAdapter.java
new file mode 100644
index 000000000..11dc4d769
--- /dev/null
+++ b/app/src/main/java/app/fedilab/android/ui/drawer/FollowedTagAdapter.java
@@ -0,0 +1,79 @@
+package app.fedilab.android.ui.drawer;
+/* 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.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+import app.fedilab.android.client.entities.api.Tag;
+import app.fedilab.android.databinding.DrawerListBinding;
+
+
+public class FollowedTagAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ private final List<Tag> tagList;
+ public ActionOnTag actionOnTag;
+
+ public FollowedTagAdapter(List<Tag> tagList) {
+ this.tagList = tagList;
+ }
+
+
+ public int getCount() {
+ return tagList.size();
+ }
+
+ public Tag getItem(int position) {
+ return tagList.get(position);
+ }
+
+ @NonNull
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ DrawerListBinding itemBinding = DrawerListBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
+ return new ListViewHolder(itemBinding);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
+ Tag tag = tagList.get(position);
+ ListViewHolder holder = (ListViewHolder) viewHolder;
+ holder.binding.title.setText(tag.name);
+ holder.binding.title.setOnClickListener(v -> actionOnTag.click(tag));
+ }
+
+ @Override
+ public int getItemCount() {
+ return tagList.size();
+ }
+
+
+ public interface ActionOnTag {
+ void click(Tag tag);
+ }
+
+ public static class ListViewHolder extends RecyclerView.ViewHolder {
+ DrawerListBinding binding;
+
+ ListViewHolder(DrawerListBinding itemView) {
+ super(itemView.getRoot());
+ binding = itemView;
+ }
+ }
+}
diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/ReorderVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/ReorderVM.java
index 4f3565b3d..49854552b 100644
--- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/ReorderVM.java
+++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/ReorderVM.java
@@ -112,6 +112,25 @@ public class ReorderVM extends AndroidViewModel {
}
+ public LiveData<Pinned> getAllPinned() {
+ pinnedMutableLiveData = new MutableLiveData<>();
+ new Thread(() -> {
+ Pinned pinned = null;
+ try {
+ pinned = new Pinned(getApplication().getApplicationContext()).getAllPinned(currentAccount);
+
+ } catch (DBException e) {
+ e.printStackTrace();
+ }
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Pinned finalPinned = pinned;
+ Runnable myRunnable = () -> pinnedMutableLiveData.setValue(finalPinned);
+ mainHandler.post(myRunnable);
+ }).start();
+ return pinnedMutableLiveData;
+ }
+
+
public LiveData<BottomMenu> getBottomMenu() {
bottomMenuMutableLiveData = new MutableLiveData<>();
new Thread(() -> {
diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/TagVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/TagVM.java
index 8f9b5af33..62b903270 100644
--- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/TagVM.java
+++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/TagVM.java
@@ -28,8 +28,6 @@ import java.util.concurrent.TimeUnit;
import app.fedilab.android.client.endpoints.MastodonTagService;
import app.fedilab.android.client.entities.api.Pagination;
-import app.fedilab.android.client.entities.api.Status;
-import app.fedilab.android.client.entities.api.Statuses;
import app.fedilab.android.client.entities.api.Tag;
import app.fedilab.android.client.entities.api.Tags;
import app.fedilab.android.helper.Helper;
@@ -76,19 +74,15 @@ public class TagVM extends AndroidViewModel {
/**
* Return followed tags with pagination
*
- * @return {@link LiveData} containing a {@link Statuses}. Note: Not to be confused with {@link Status}
+ * @return {@link LiveData} containing a {@link Tags}. Note: Not to be confused with {@link Tag}
*/
- public LiveData<Tags> followedTags(@NonNull String instance, String token,
- String maxId,
- String sinceId,
- String minId,
- int count) {
+ public LiveData<Tags> followedTags(@NonNull String instance, String token) {
tagsMutableLiveData = new MutableLiveData<>();
MastodonTagService mastodonTagService = init(instance);
new Thread(() -> {
List<Tag> tagList = null;
Pagination pagination = null;
- Call<List<Tag>> followedTagsListCall = mastodonTagService.getFollowedTags(token, maxId, sinceId, minId, count);
+ Call<List<Tag>> followedTagsListCall = mastodonTagService.getFollowedTags(token);
if (followedTagsListCall != null) {
try {
Response<List<Tag>> tagsResponse = followedTagsListCall.execute();
@@ -112,6 +106,37 @@ public class TagVM extends AndroidViewModel {
}
/**
+ * Return tag
+ *
+ * @return {@link LiveData} containing a {@link Tag}
+ */
+ public LiveData<Tag> getTag(@NonNull String instance, String token,
+ String tagName) {
+ tagMutableLiveData = new MutableLiveData<>();
+ MastodonTagService mastodonTagService = init(instance);
+ new Thread(() -> {
+ Tag tag = null;
+ Call<Tag> tagCall = mastodonTagService.getTag(token, tagName);
+ if (tagCall != null) {
+ try {
+ Response<Tag> tagResponse = tagCall.execute();
+ if (tagResponse.isSuccessful()) {
+ tag = tagResponse.body();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ Tag finalTag = tag;
+ Runnable myRunnable = () -> tagMutableLiveData.setValue(finalTag);
+ mainHandler.post(myRunnable);
+ }).start();
+ return tagMutableLiveData;
+ }
+
+
+ /**
* Follow a tag
*
* @return {@link LiveData} containing an {@link Tag}
diff --git a/app/src/main/res/drawable/ic_baseline_post_add_24.xml b/app/src/main/res/drawable/ic_baseline_post_add_24.xml
new file mode 100644
index 000000000..59bf92d41
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_post_add_24.xml
@@ -0,0 +1,22 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="#FFFFFF"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M17,19.22H5V7h7V5H5C3.9,5 3,5.9 3,7v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-7h-2V19.22z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,2h-2v3h-3c0.01,0.01 0,2 0,2h3v2.99c0.01,0.01 2,0 2,0V7h3V5h-3V2z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M7,9h8v2h-8z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M7,12l0,2l8,0l0,-2l-3,0z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M7,15h8v2h-8z" />
+</vector>
diff --git a/app/src/main/res/drawable/ic_baseline_tag_24.xml b/app/src/main/res/drawable/ic_baseline_tag_24.xml
new file mode 100644
index 000000000..e996ae23d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_tag_24.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="#FFFFFF"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20,10L20,8h-4L16,4h-2v4h-4L10,4L8,4v4L4,8v2h4v4L4,14v2h4v4h2v-4h4v4h2v-4h4v-2h-4v-4h4zM14,14h-4v-4h4v4z" />
+</vector>
diff --git a/app/src/main/res/layout/activity_followed_tags.xml b/app/src/main/res/layout/activity_followed_tags.xml
new file mode 100644
index 000000000..6a1558ee4
--- /dev/null
+++ b/app/src/main/res/layout/activity_followed_tags.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="@dimen/fab_margin">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/recycler_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipToPadding="false"
+ android:scrollbars="none" />
+
+ <TextView
+ android:id="@+id/not_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:padding="10dp"
+ android:text="@string/action_followed_tag_empty"
+ android:textSize="20sp"
+ android:textStyle="bold"
+ android:typeface="serif"
+ android:visibility="gone" />
+
+ <androidx.fragment.app.FragmentContainerView
+ android:id="@+id/fragment_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
+</RelativeLayout>
diff --git a/app/src/main/res/layout/popup_add_followed_tagt.xml b/app/src/main/res/layout/popup_add_followed_tagt.xml
new file mode 100644
index 000000000..2b9bdc0a1
--- /dev/null
+++ b/app/src/main/res/layout/popup_add_followed_tagt.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="@dimen/fab_margin"
+ android:orientation="vertical">
+
+ <androidx.appcompat.widget.AppCompatEditText
+ android:id="@+id/add_tag"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:layout_marginBottom="20dp"
+ android:hint="@string/write_the_tag_to_follow"
+ android:inputType="text"
+ android:singleLine="true" />
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml
index 553d01f4f..c82203cc2 100644
--- a/app/src/main/res/menu/activity_main_drawer.xml
+++ b/app/src/main/res/menu/activity_main_drawer.xml
@@ -26,6 +26,10 @@
android:icon="@drawable/ic_baseline_view_list_24"
android:title="@string/action_lists" />
<item
+ android:id="@+id/nav_followed_tags"
+ android:icon="@drawable/ic_baseline_tag_24"
+ android:title="@string/followed_tags" />
+ <item
android:id="@+id/nav_follow_requests"
android:icon="@drawable/ic_baseline_group_add_24"
android:title="@string/follow_request"
diff --git a/app/src/main/res/menu/menu_followed_tag.xml b/app/src/main/res/menu/menu_followed_tag.xml
new file mode 100644
index 000000000..4d713bc9d
--- /dev/null
+++ b/app/src/main/res/menu/menu_followed_tag.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/action_unfollow"
+ android:icon="@drawable/ic_baseline_delete_24"
+ android:title="@string/action_unfollow_tag"
+ app:showAsAction="ifRoom" />
+</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/menu_hashtag.xml b/app/src/main/res/menu/menu_hashtag.xml
new file mode 100644
index 000000000..3a6740ff0
--- /dev/null
+++ b/app/src/main/res/menu/menu_hashtag.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/action_follow_tag"
+ android:icon="@drawable/ic_baseline_post_add_24"
+ android:title="@string/follow_tag"
+ app:showAsAction="ifRoom" />
+ <item
+ android:id="@+id/action_add_timeline"
+ android:icon="@drawable/ic_baseline_add_24"