finalized user field support, restructured ViewPager adapter

This commit is contained in:
nuclearfog 2023-07-10 21:12:45 +02:00
parent 211ee4d22c
commit 60df3dd016
No known key found for this signature in database
GPG Key ID: 03488A185C476379
21 changed files with 384 additions and 104 deletions

View File

@ -1,50 +0,0 @@
package org.nuclearfog.twidda.backend.api.mastodon.impl;
import org.json.JSONException;
import org.json.JSONObject;
import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.model.User.Field;
/**
* User fields implementation of Mastodon
*
* @author nuclearfog
*/
public class MastodonField implements Field {
private static final long serialVersionUID = 2278113885084330065L;
private String key;
private String value;
private long timestamp = 0L;
/**
* @param json fields json
*/
public MastodonField(JSONObject json) throws JSONException {
key = json.getString("name");
value = json.getString("value");
String timeStr = json.getString("verified_at");
if (!timeStr.equals("null")) {
timestamp = StringUtils.getTime(timeStr, StringUtils.TIME_MASTODON);
}
}
@Override
public String getKey() {
return key;
}
@Override
public String getValue() {
return value;
}
@Override
public long getTimestamp() {
return timestamp;
}
}

View File

@ -6,10 +6,6 @@ import androidx.annotation.Nullable;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Document.OutputSettings;
import org.jsoup.safety.Safelist;
import org.nuclearfog.twidda.backend.utils.StringUtils; import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.model.Card; import org.nuclearfog.twidda.model.Card;
import org.nuclearfog.twidda.model.Emoji; import org.nuclearfog.twidda.model.Emoji;
@ -31,8 +27,6 @@ public class MastodonStatus implements Status {
private static final long serialVersionUID = 1184375228249441241L; private static final long serialVersionUID = 1184375228249441241L;
private static final OutputSettings OUTPUT_SETTINGS = new OutputSettings().prettyPrint(false);
private long id; private long id;
private long replyId; private long replyId;
private long replyUserId; private long replyUserId;
@ -90,24 +84,7 @@ public class MastodonStatus implements Status {
sensitive = json.optBoolean("sensitive", false); sensitive = json.optBoolean("sensitive", false);
spoiler = json.optBoolean("spoiler_text", false); spoiler = json.optBoolean("spoiler_text", false);
bookmarked = json.optBoolean("bookmarked", false); bookmarked = json.optBoolean("bookmarked", false);
String text = json.optString("content", ""); text = StringUtils.extractText(json.optString("content", ""));
try {
// create newlines at every <br> or <p> tag
Document jsoupDoc = Jsoup.parse(text);
jsoupDoc.outputSettings(OUTPUT_SETTINGS);
jsoupDoc.select("br").after("\\n");
jsoupDoc.select("p").before("\\n");
String str = jsoupDoc.html().replace("\\n", "\n");
text = Jsoup.clean(str, "", Safelist.none(), OUTPUT_SETTINGS);
text = text.replace("&lt;", "<").replace("&gt;", ">").replace("&amp;", "&").replace("&nbsp;", "\u00A0");
if (text.startsWith("\n")) {
text = text.substring(1);
}
} catch (Exception exception) {
// use fallback text string from json
}
this.text = text;
if (author.getId() != currentUserId) if (author.getId() != currentUserId)
mentions = author.getScreenname() + ' '; mentions = author.getScreenname() + ' ';

View File

@ -248,4 +248,47 @@ public class MastodonUser implements User {
public String toString() { public String toString() {
return "name=\"" + getScreenname() + "\""; return "name=\"" + getScreenname() + "\"";
} }
/**
*
*/
private static class MastodonField implements Field {
private static final long serialVersionUID = 2278113885084330065L;
private String key;
private String value;
private long timestamp = 0L;
/**
* @param json fields json
*/
public MastodonField(JSONObject json) throws JSONException {
key = json.getString("name");
value = StringUtils.extractText(json.optString("value", ""));
String timeStr = json.getString("verified_at");
if (!timeStr.equals("null")) {
timestamp = StringUtils.getTime(timeStr, StringUtils.TIME_MASTODON);
}
}
@Override
public String getKey() {
return key;
}
@Override
public String getValue() {
return value;
}
@Override
public long getTimestamp() {
return timestamp;
}
}
} }

View File

@ -3,6 +3,9 @@ package org.nuclearfog.twidda.backend.utils;
import android.content.res.Resources; import android.content.res.Resources;
import android.util.Base64; import android.util.Base64;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Safelist;
import org.nuclearfog.twidda.BuildConfig; import org.nuclearfog.twidda.BuildConfig;
import org.nuclearfog.twidda.R; import org.nuclearfog.twidda.R;
@ -61,6 +64,8 @@ public class StringUtils {
private static final TimeZone TIME_ZONE = TimeZone.getDefault(); private static final TimeZone TIME_ZONE = TimeZone.getDefault();
private static final Document.OutputSettings OUTPUT_SETTINGS = new Document.OutputSettings().prettyPrint(false);
/** /**
* fallback date if parsing failed * fallback date if parsing failed
*/ */
@ -194,6 +199,31 @@ public class StringUtils {
return buf.toString(); return buf.toString();
} }
/**
* extract text from html doc
*
* @param text html string
* @return text string
*/
public static String extractText(String text) {
try {
// create newlines at every <br> or <p> tag
Document jsoupDoc = Jsoup.parse(text);
jsoupDoc.outputSettings(OUTPUT_SETTINGS);
jsoupDoc.select("br").after("\\n");
jsoupDoc.select("p").before("\\n");
String str = jsoupDoc.html().replace("\\n", "\n");
text = Jsoup.clean(str, "", Safelist.none(), OUTPUT_SETTINGS);
text = text.replace("&lt;", "<").replace("&gt;", ">").replace("&amp;", "&").replace("&nbsp;", "\u00A0");
if (text.startsWith("\n")) {
text = text.substring(1);
}
} catch (Exception exception) {
// use fallback text string from json
}
return text;
}
/** /**
* convert time strings from different APIs to the local format * convert time strings from different APIs to the local format
* *

View File

@ -4,6 +4,7 @@ import androidx.annotation.NonNull;
import org.nuclearfog.twidda.model.User.Field; import org.nuclearfog.twidda.model.User.Field;
import java.util.Arrays;
import java.util.LinkedList; import java.util.LinkedList;
/** /**
@ -24,6 +25,11 @@ public class Fields extends LinkedList<Field> {
} }
public Fields(Field[] fields) {
super(Arrays.asList(fields));
}
@NonNull @NonNull
@Override @Override
public String toString() { public String toString() {

View File

@ -25,7 +25,7 @@ import androidx.viewpager2.widget.ViewPager2;
import org.nuclearfog.twidda.R; import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles; import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter; import org.nuclearfog.twidda.ui.adapter.fragments.FragmentAdapter;
import org.nuclearfog.twidda.ui.dialogs.ProgressDialog; import org.nuclearfog.twidda.ui.dialogs.ProgressDialog;
import org.nuclearfog.twidda.ui.views.TabSelector; import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener; import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;

View File

@ -66,7 +66,7 @@ import org.nuclearfog.twidda.config.Configuration;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.Relation; import org.nuclearfog.twidda.model.Relation;
import org.nuclearfog.twidda.model.User; import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter; import org.nuclearfog.twidda.ui.adapter.fragments.ProfileAdapter;
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog; import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog;
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog.OnConfirmListener; import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog.OnConfirmListener;
import org.nuclearfog.twidda.ui.views.LockableLinearLayout; import org.nuclearfog.twidda.ui.views.LockableLinearLayout;
@ -137,7 +137,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
private AsyncCallback<EmojiResult> usernameUpdate = this::onUsernameUpdate; private AsyncCallback<EmojiResult> usernameUpdate = this::onUsernameUpdate;
private AsyncCallback<EmojiResult> userDescriptionUpdate = this::onUserDescriptionUpdate; private AsyncCallback<EmojiResult> userDescriptionUpdate = this::onUserDescriptionUpdate;
private FragmentAdapter adapter; private ProfileAdapter adapter;
private GlobalSettings settings; private GlobalSettings settings;
private Picasso picasso; private Picasso picasso;
private ConfirmDialog confirmDialog; private ConfirmDialog confirmDialog;
@ -192,7 +192,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
tabSelector = findViewById(R.id.profile_tab); tabSelector = findViewById(R.id.profile_tab);
viewPager = findViewById(R.id.profile_pager); viewPager = findViewById(R.id.profile_pager);
adapter = new FragmentAdapter(this); adapter = new ProfileAdapter(this);
relationLoader = new RelationLoader(this); relationLoader = new RelationLoader(this);
domainAction = new DomainAction(this); domainAction = new DomainAction(this);
userLoader = new UserLoader(this); userLoader = new UserLoader(this);
@ -261,13 +261,14 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
RelationParam param = new RelationParam(userId, RelationParam.LOAD); RelationParam param = new RelationParam(userId, RelationParam.LOAD);
relationLoader.execute(param, relationCallback); relationLoader.execute(param, relationCallback);
} }
adapter.setupProfilePage(userId); adapter.setUser(userId);
if (settings.likeEnabled()) { if (settings.getLogin().getConfiguration() == Configuration.MASTODON && userId != settings.getLogin().getId()) {
tabSelector.addTabIcons(R.array.profile_tab_icons);
} else if (settings.likeEnabled()) {
tabSelector.addTabIcons(R.array.profile_tab_icons_like); tabSelector.addTabIcons(R.array.profile_tab_icons_like);
} else { } else {
tabSelector.addTabIcons(R.array.profile_tab_icons); tabSelector.addTabIcons(R.array.profile_tab_icons_favorite);
} }
tabSelector.addOnTabSelectedListener(this); tabSelector.addOnTabSelectedListener(this);
following.setOnClickListener(this); following.setOnClickListener(this);
follower.setOnClickListener(this); follower.setOnClickListener(this);
@ -863,6 +864,9 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
emojiLoader.execute(param, userDescriptionUpdate); emojiLoader.execute(param, userDescriptionUpdate);
} }
} }
if (user.getFields().length > 0) {
adapter.setFields(user.getFields());
}
} }
/** /**

View File

@ -27,7 +27,7 @@ import org.nuclearfog.twidda.backend.utils.ErrorUtils;
import org.nuclearfog.twidda.config.Configuration; import org.nuclearfog.twidda.config.Configuration;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.Trend; import org.nuclearfog.twidda.model.Trend;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter; import org.nuclearfog.twidda.ui.adapter.fragments.FragmentAdapter;
import org.nuclearfog.twidda.ui.views.TabSelector; import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener; import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;

View File

@ -34,7 +34,7 @@ import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorUtils; import org.nuclearfog.twidda.backend.utils.ErrorUtils;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.UserList; import org.nuclearfog.twidda.model.UserList;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter; import org.nuclearfog.twidda.ui.adapter.fragments.FragmentAdapter;
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog; import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog;
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog.OnConfirmListener; import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog.OnConfirmListener;
import org.nuclearfog.twidda.ui.views.TabSelector; import org.nuclearfog.twidda.ui.views.TabSelector;

View File

@ -20,7 +20,7 @@ import androidx.viewpager2.widget.ViewPager2;
import org.nuclearfog.twidda.R; import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles; import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter; import org.nuclearfog.twidda.ui.adapter.fragments.FragmentAdapter;
import org.nuclearfog.twidda.ui.views.TabSelector; import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener; import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;

View File

@ -27,7 +27,7 @@ import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorUtils; import org.nuclearfog.twidda.backend.utils.ErrorUtils;
import org.nuclearfog.twidda.config.Configuration; import org.nuclearfog.twidda.config.Configuration;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter; import org.nuclearfog.twidda.ui.adapter.fragments.FragmentAdapter;
import org.nuclearfog.twidda.ui.views.TabSelector; import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener; import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;

View File

@ -5,25 +5,33 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView.Adapter; import androidx.recyclerview.widget.RecyclerView.Adapter;
import org.nuclearfog.tag.Tagger.OnTagClickListener;
import org.nuclearfog.twidda.model.lists.Fields; import org.nuclearfog.twidda.model.lists.Fields;
import org.nuclearfog.twidda.ui.adapter.holder.FieldHolder; import org.nuclearfog.twidda.ui.adapter.holder.FieldHolder;
/** /**
* RecyclerView adapter used to show a list of {@link org.nuclearfog.twidda.model.User.Field}
*
* @author nuclearfog * @author nuclearfog
*/ */
public class FieldAdapter extends Adapter<FieldHolder> { public class FieldAdapter extends Adapter<FieldHolder> implements OnTagClickListener {
private OnLinkClickListener listener;
private Fields fields = new Fields(); private Fields fields = new Fields();
public FieldAdapter() { /**
*
*/
public FieldAdapter(OnLinkClickListener listener) {
this.listener = listener;
} }
@NonNull @NonNull
@Override @Override
public FieldHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public FieldHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new FieldHolder(parent); return new FieldHolder(parent, this);
} }
@ -39,14 +47,46 @@ public class FieldAdapter extends Adapter<FieldHolder> {
} }
@Override
public void onTagClick(String tag) {
}
@Override
public void onLinkClick(String link) {
listener.onLinkClick(link);
}
/**
* replace all existing items with new ones
*
* @param fields items to insert
*/
public void replaceItems(Fields fields) { public void replaceItems(Fields fields) {
this.fields.clear(); this.fields.clear();
this.fields.addAll(fields); this.fields.addAll(fields);
notifyDataSetChanged(); notifyDataSetChanged();
} }
/**
* get all items
*
* @return Field list
*/
public Fields getItems() { public Fields getItems() {
return new Fields(fields); return new Fields(fields);
} }
/**
* Click listener for url
*/
public interface OnLinkClickListener {
/**
* called on url click
*
* @param url url string
*/
void onLinkClick(String url);
}
} }

View File

@ -1,4 +1,4 @@
package org.nuclearfog.twidda.ui.adapter; package org.nuclearfog.twidda.ui.adapter.fragments;
import android.os.Bundle; import android.os.Bundle;

View File

@ -0,0 +1,89 @@
package org.nuclearfog.twidda.ui.adapter.fragments;
import android.os.Bundle;
import androidx.fragment.app.FragmentActivity;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.User;
import org.nuclearfog.twidda.model.lists.Fields;
import org.nuclearfog.twidda.ui.fragments.FieldFragment;
import org.nuclearfog.twidda.ui.fragments.ListFragment;
import org.nuclearfog.twidda.ui.fragments.StatusFragment;
/**
* ViewPager adapter used to show profile timelines
*
* @author nuclearfog
*/
public class ProfileAdapter extends ViewPagerAdapter {
private GlobalSettings settings;
/**
*
*/
public ProfileAdapter(FragmentActivity fragmentActivity) {
super(fragmentActivity);
settings = GlobalSettings.get(fragmentActivity);
}
/**
* create adapter items
*
* @param userId ID of the user profile
*/
public void setUser(long userId) {
// user timeline
Bundle paramUser = new Bundle();
paramUser.putLong(StatusFragment.KEY_ID, userId);
paramUser.putInt(StatusFragment.KEY_MODE, StatusFragment.MODE_USER);
ListFragment statusFragment = new StatusFragment();
statusFragment.setArguments(paramUser);
// user favorits
Bundle paramFavorite = new Bundle();
paramFavorite.putLong(StatusFragment.KEY_ID, userId);
paramFavorite.putInt(StatusFragment.KEY_MODE, StatusFragment.MODE_FAVORIT);
ListFragment favoriteFragment = new StatusFragment();
favoriteFragment.setArguments(paramFavorite);
// user bookmarks
Bundle paramBookmark = new Bundle();
paramBookmark.putLong(StatusFragment.KEY_ID, userId);
paramBookmark.putInt(StatusFragment.KEY_MODE, StatusFragment.MODE_BOOKMARK);
ListFragment bookmarkFragment = new StatusFragment();
bookmarkFragment.setArguments(paramBookmark);
// user fields
ListFragment fieldFragment = new FieldFragment();
fragments.clear();
fragments.add(statusFragment);
switch (settings.getLogin().getConfiguration()) {
case MASTODON:
if (settings.getLogin().getId() == userId) {
fragments.add(favoriteFragment);
fragments.add(bookmarkFragment);
}
fragments.add(fieldFragment);
break;
case TWITTER1:
case TWITTER2:
fragments.add(favoriteFragment);
break;
}
notifyDataSetChanged();
}
/**
* put user fields into FieldFragment
*
* @param fields user fields
*/
public void setFields(User.Field[] fields) {
for (ListFragment fragment : fragments) {
if (fragment instanceof FieldFragment) {
((FieldFragment) fragment).setItems(new Fields(fields));
}
}
}
}

View File

@ -0,0 +1,76 @@
package org.nuclearfog.twidda.ui.adapter.fragments;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import org.nuclearfog.twidda.ui.fragments.ListFragment;
import java.util.ArrayList;
/**
* @author nuclearfog
*/
public class ViewPagerAdapter extends FragmentStateAdapter {
protected ArrayList<ListFragment> fragments = new ArrayList<>();
/**
*
*/
public ViewPagerAdapter(FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
@Override
public final long getItemId(int position) {
return fragments.get(position).getSessionId();
}
@Override
public final boolean containsItem(long itemId) {
for (ListFragment fragment : fragments) {
if (fragment.getSessionId() == itemId)
return true;
}
return false;
}
@NonNull
@Override
public final Fragment createFragment(int position) {
return fragments.get(position);
}
@Override
public final int getItemCount() {
return fragments.size();
}
/**
* called when app settings change
*/
public void notifySettingsChanged() {
for (ListFragment fragment : fragments) {
if (!fragment.isDetached()) {
fragment.reset();
}
}
}
/**
* called to scroll page to top
*
* @param index tab position of page
*/
public void scrollToTop(int index) {
if (!fragments.get(index).isDetached()) {
fragments.get(index).onTabChange();
}
}
}

View File

@ -1,37 +1,64 @@
package org.nuclearfog.twidda.ui.adapter.holder; package org.nuclearfog.twidda.ui.adapter.holder;
import android.graphics.Color;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView.ViewHolder; import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import org.nuclearfog.tag.Tagger;
import org.nuclearfog.tag.Tagger.OnTagClickListener;
import org.nuclearfog.twidda.R; import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.StringUtils; import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.User.Field; import org.nuclearfog.twidda.model.User.Field;
/**
* ViewHolder for {@link org.nuclearfog.twidda.ui.adapter.FieldAdapter}
*
* @author nuclearfog
*/
public class FieldHolder extends ViewHolder { public class FieldHolder extends ViewHolder {
private View verified; private View verified;
private TextView key, value, time; private TextView key, value, time;
private GlobalSettings settings;
private OnTagClickListener listener;
public FieldHolder(ViewGroup parent) { /**
*
*/
public FieldHolder(ViewGroup parent, OnTagClickListener listener) {
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_field, parent, false)); super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_field, parent, false));
CardView background = (CardView) itemView;
ViewGroup container = itemView.findViewById(R.id.item_field_container);
verified = itemView.findViewById(R.id.item_field_verified); verified = itemView.findViewById(R.id.item_field_verified);
key = itemView.findViewById(R.id.item_field_key); key = itemView.findViewById(R.id.item_field_key);
value = itemView.findViewById(R.id.item_field_value); value = itemView.findViewById(R.id.item_field_value);
time = itemView.findViewById(R.id.item_field_timestamp); time = itemView.findViewById(R.id.item_field_timestamp);
settings = GlobalSettings.get(parent.getContext());
this.listener = listener;
value.setMovementMethod(LinkMovementMethod.getInstance());
background.setCardBackgroundColor(settings.getCardColor());
AppStyles.setTheme(container, Color.TRANSPARENT);
} }
/**
* set view content
*/
public void setContent(Field field) { public void setContent(Field field) {
key.setText(field.getKey()); key.setText(field.getKey());
value.setText(field.getValue()); value.setText(Tagger.makeTextWithLinks(field.getValue(), settings.getHighlightColor(), listener));
if (field.getTimestamp() != 0L) { if (field.getTimestamp() != 0L) {
verified.setVisibility(View.VISIBLE); verified.setVisibility(View.VISIBLE);
time.setText(R.string.field_verified_in); time.setText(R.string.field_verified);
time.append(StringUtils.formatCreationTime(time.getResources(), field.getTimestamp())); time.append(StringUtils.formatCreationTime(time.getResources(), field.getTimestamp()));
} else { } else {
verified.setVisibility(View.GONE); verified.setVisibility(View.GONE);

View File

@ -6,10 +6,19 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.nuclearfog.twidda.backend.utils.LinkUtils;
import org.nuclearfog.twidda.model.lists.Fields; import org.nuclearfog.twidda.model.lists.Fields;
import org.nuclearfog.twidda.ui.adapter.FieldAdapter; import org.nuclearfog.twidda.ui.adapter.FieldAdapter;
import org.nuclearfog.twidda.ui.adapter.FieldAdapter.OnLinkClickListener;
public class FieldFragment extends ListFragment { /**
* User field list fragment
*
* @author nuclearfog
*/
public class FieldFragment extends ListFragment implements OnLinkClickListener {
private static final String KEY_SAVE = "fields-save";
private FieldAdapter adapter; private FieldAdapter adapter;
@ -17,18 +26,32 @@ public class FieldFragment extends ListFragment {
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
adapter = new FieldAdapter(); adapter = new FieldAdapter(this);
setAdapter(adapter); setAdapter(adapter);
if (savedInstanceState != null) {
Object data = savedInstanceState.getSerializable(KEY_SAVE);
if (data instanceof Fields) {
adapter.replaceItems((Fields) data);
}
}
disableSwipe(); disableSwipe();
} }
@Override @Override
public void onSaveInstanceState(@NonNull Bundle outState) { public void onSaveInstanceState(@NonNull Bundle outState) {
Fields items = adapter.getItems();
outState.putSerializable(KEY_SAVE, items);
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@Override
public void onLinkClick(String url) {
LinkUtils.openLink(requireActivity(), url);
}
@Override @Override
protected void onReload() { protected void onReload() {
} }
@ -38,7 +61,11 @@ public class FieldFragment extends ListFragment {
protected void onReset() { protected void onReset() {
} }
/**
* set field items
*
* @param items new items to show in a list
*/
public void setItems(Fields items) { public void setItems(Fields items) {
if (adapter != null) { if (adapter != null) {
adapter.replaceItems(items); adapter.replaceItems(items);

View File

@ -1,11 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/CardViewStyle"> style="@style/CardViewStyle">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/item_field_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="@dimen/item_field_card_padding"> android:padding="@dimen/item_field_card_padding">
@ -18,7 +20,8 @@
android:layout_margin="@dimen/item_field_layout_margin" android:layout_margin="@dimen/item_field_layout_margin"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/item_field_key" app:layout_constraintTop_toTopOf="@id/item_field_key"
app:layout_constraintBottom_toBottomOf="@id/item_field_key" /> app:layout_constraintBottom_toBottomOf="@id/item_field_key"
tools:ignore="ContentDescription" />
<TextView <TextView
android:id="@+id/item_field_key" android:id="@+id/item_field_key"
@ -38,6 +41,7 @@
android:maxLines="2" android:maxLines="2"
android:layout_margin="@dimen/item_field_layout_margin" android:layout_margin="@dimen/item_field_layout_margin"
android:textSize="@dimen/item_field_textsize_value" android:textSize="@dimen/item_field_textsize_value"
android:linksClickable="true"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/item_field_key" app:layout_constraintTop_toBottomOf="@id/item_field_key"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />

View File

@ -69,15 +69,14 @@
<TextView <TextView
android:id="@+id/item_message_screenname" android:id="@+id/item_message_screenname"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dmitem_text_margin" android:layout_marginStart="@dimen/dmitem_text_margin"
android:layout_marginEnd="@dimen/dmitem_text_margin"
android:lines="1" android:lines="1"
android:textSize="@dimen/dmitem_textsize_name" android:textSize="@dimen/dmitem_textsize_name"
app:layout_constraintStart_toEndOf="@id/item_message_private" app:layout_constraintStart_toEndOf="@id/item_message_private"
app:layout_constraintTop_toBottomOf="@id/item_message_username" app:layout_constraintTop_toBottomOf="@id/item_message_username"
app:layout_constraintBottom_toBottomOf="@id/item_message_profile" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed" /> app:layout_constraintHorizontal_chainStyle="packed" />
@ -104,6 +103,7 @@
android:id="@+id/item_message_attachment_list" android:id="@+id/item_message_attachment_list"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="@dimen/dmitem_indicator_size" android:layout_height="@dimen/dmitem_indicator_size"
android:layout_marginTop="@dimen/dmitem_text_margin"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/item_message_text" app:layout_constraintTop_toBottomOf="@id/item_message_text"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />

View File

@ -49,15 +49,22 @@
</integer-array> </integer-array>
<integer-array name="profile_tab_icons"> <integer-array name="profile_tab_icons">
<item>@drawable/home</item>
<item>@drawable/info</item>
</integer-array>
<integer-array name="profile_tab_icons_favorite">
<item>@drawable/home</item> <item>@drawable/home</item>
<item>@drawable/favorite</item> <item>@drawable/favorite</item>
<item>@drawable/bookmark</item> <item>@drawable/bookmark</item>
<item>@drawable/info</item>
</integer-array> </integer-array>
<integer-array name="profile_tab_icons_like"> <integer-array name="profile_tab_icons_like">
<item>@drawable/home</item> <item>@drawable/home</item>
<item>@drawable/like</item> <item>@drawable/like</item>
<item>@drawable/bookmark</item> <item>@drawable/bookmark</item>
<item>@drawable/info</item>
</integer-array> </integer-array>
<integer-array name="userlist_tab_icons"> <integer-array name="userlist_tab_icons">

View File

@ -321,7 +321,7 @@
<string name="status_translate_text">translate</string> <string name="status_translate_text">translate</string>
<string name="status_translate_source">Translated by:\u0020</string> <string name="status_translate_source">Translated by:\u0020</string>
<string name="status_translate_source_language">Language:\u0020</string> <string name="status_translate_source_language">Language:\u0020</string>
<string name="field_verified_in">verified in\u0020</string> <string name="field_verified">verified:\u0020</string>
<string name="confirm_remove_account">remove account from list?</string> <string name="confirm_remove_account">remove account from list?</string>
<string name="confirm_remove_filter">delete filter?</string> <string name="confirm_remove_filter">delete filter?</string>
<string name="account_user_unnamed">\'unnamed\'</string> <string name="account_user_unnamed">\'unnamed\'</string>