Merge upstream redesign (#714)
* merge toolbar fragment * Fix store screenshot generator * Fix alert color * Fix #609 * Fix crash * bigger hitbox for chips * support mastodon languages * merge ui utils * merge stuff * fix icon * ensure 48dp touch target * init local prefs, add helper function for enum values * update compose action layout * merge compose-adj files * update extended footer * fix poll wrong option checked closes sk22#641 * no border when disabled closes sk22#640 * Fix #610 * Minor fixes * Fix alert color * Fix #609 * Fix crash * Fix #610 * Minor fixes * add resources * more compatible mastodon language * fix html parser * mark as read on refresh * update tab bar * tweak m3 buttons * update compose-adj files * tweak and update styles * m3 expand button * flag icon should be 18dp, actually * More minor fixes closes #612 * More minor fixes closes #612 * Bump version * fix no create status event when redrafting * add material 3 assets * New translations strings.xml (Greek) * New translations strings.xml (Greek) * New translations strings.xml (Italian) * New translations strings.xml (Greek) * New translations strings.xml (Italian) * New translations strings.xml (Thai) * New translations strings.xml (Thai) * New translations strings.xml (Italian) * New translations strings.xml (Thai) * use new buttons for profile fragment * merge compose fragment * merge all the styles! oh dear * New translations full_description.txt (Indonesian) * New translations full_description.txt (Chinese Simplified) * New translations strings.xml (Chinese Simplified) * New translations full_description.txt (Chinese Simplified) * Fix #615 * Minor fixes * Fix #611 * A bunch of crash fixes * New translations strings.xml (Greek) * Make the default server configurable * Pass the system timezone to server when signing up * New translations strings.xml (Chinese Simplified) * New translations strings.xml (Japanese) * Fix #615 * Minor fixes * Fix #611 * A bunch of crash fixes * Make the default server configurable * Pass the system timezone to server when signing up * oops. accidentally pasted the commit message in the code * Remove unused code that caused a crash for some users ¯\_(ツ)_/¯ * New translations strings.xml (Japanese) * New translations strings.xml (Japanese) * Remove unused code that caused a crash for some users ¯\_(ツ)_/¯ * New translations strings.xml (Polish) * New translations strings.xml (Polish) * New translations strings.xml (Turkish) * New translations strings.xml (Belarusian) * prepare merging profile fragment * merge profile fragment * New translations strings.xml (Belarusian) * New translations strings.xml (Greek) * fix icon padding * apply post header changes * minor margin tweaks * fix footer buttons * fix header announcement buttons * New translations strings.xml (Japanese) * New translations strings.xml (Japanese) * New translations strings.xml (Japanese) * New translations strings.xml (Japanese) * New translations strings.xml (Japanese) * New translations strings.xml (Japanese) * New translations full_description.txt (Japanese) * New translations strings.xml (Icelandic) * New translations strings.xml (Icelandic) * New translations strings.xml (Icelandic) * fix replying * New translations strings.xml (Icelandic) * fix translate button * fix more button visibility * fix counts label styling * fix disabled boost button opacity * fix tab layouts * fix notification icon color crash * New translations strings.xml (Greek) * implement elevation listener in home tab * fix elevation and listener in home tab * add elevation scroll listener to notifications * New translations strings.xml (Scottish Gaelic) * Add editorconfig So that PRs like #625 don't happen again * Crash fix * 🤔 * New translations strings.xml (Greek) * New translations strings.xml (Japanese) * New translations strings.xml (French) * New translations strings.xml (French) * New translations strings.xml (French) * fix notification elevation and integrate divider * 🤔 * Crash fix * Add editorconfig So that PRs like #625 don't happen again * New translations strings.xml (Turkish) * save interactions in cache * New translations strings.xml (Turkish) * merge new discover/search * New translations strings.xml (Bengali) * New translations strings.xml (Scottish Gaelic) * New translations strings.xml (Bengali) * merge new settings fragments * fix no auth callback always being executed * allow opening server info from profile closes sk22#593 * fix hide boosts icon color closes sk22#676 * New translations strings.xml (Turkish) * New translations strings.xml (Turkish) * New translations strings.xml (Turkish) * New translations strings.xml (Chinese Simplified) * New translations strings.xml (Turkish) * New translations strings.xml (Chinese Simplified) * New translations strings.xml (German) * New translations strings.xml (German) * New translations strings.xml (Turkish) * update fedinuke list from source; doesn't contain any modifications regarding a recent issue * New translations strings.xml (Turkish) * remove unused class * fix crash * darken m3 outline color a bit * use m3 outline again * fix misalignment closes sk22#682 * New translations strings.xml (Turkish) * New translations full_description.txt (Turkish) * New translations short_description.txt (Turkish) * fix crash * fix metadata sorting * show pronouns in header/account lists * fix broken divider line closes sk22#679 * trim pronouns * improve pronoun display * New translations strings.xml (French) * New translations strings.xml (Japanese) * fix broken federated timeline closes sk22#685 * fix broken -1 fallback behavior closes sk22#681 * don't display nothing if server about request fails closes sk22#678 * New translations strings.xml (Ukrainian) * migrate global prefs to local prefs * do confirm unfollow by default * New translations strings.xml (Ukrainian) * New translations strings.xml (Ukrainian) * New translations full_description.txt (Ukrainian) * New translations strings.xml (Ukrainian) * New translations strings.xml (Ukrainian) * New translations strings.xml (Ukrainian) * New translations strings.xml (Ukrainian) * New translations strings.xml (Ukrainian) * New translations strings.xml (Russian) * New translations strings.xml (Vietnamese) * New translations strings.xml (Ukrainian) * New translations strings.xml (Vietnamese) * New translations full_description.txt (Ukrainian) * New translations strings.xml (Ukrainian) * New translations strings.xml (Vietnamese) * New translations strings.xml (Ukrainian) * New translations strings.xml (Ukrainian) * make sure list in prefs are always mutable and nut null * New translations strings.xml (Ukrainian) * New translations strings.xml (Ukrainian) * New translations strings.xml (Russian) * fix pronouns edge case * add back fix for stretched images closes sk22#636 * fix null pointer on missing default posting language * fix default posting language not being applied * bigger username hitbox closes sk22#688 * fix rtl header username alignment closes sk22#689 * New translations strings.xml (Ukrainian) * New translations strings.xml (Ukrainian) * hopefully fix crashes closes sk22#692 * New translations strings.xml (Ukrainian) * New translations full_description.txt (Ukrainian) * fix pronoun crash * New translations strings.xml (Persian) * New translations strings.xml (Ukrainian) * re-add true black mode * asterisk can be a pronoun * New translations strings.xml (Persian) * true black mode fixes and clean-ups * material 3 button background for switcher * darker tab bar selected background * better align follow/following button widths * restore rainbow refresh colors * fix search transition * fix min width issue with switcher button * fix no elevation when true black is enabled in light theme * use statusForContent to determine spoilerRevealed closes sk22#694 * New translations strings.xml (Persian) * New translations strings.xml (Persian) * New translations strings.xml (Persian) * New translations strings.xml (Persian) * New translations strings.xml (Persian) * New translations strings.xml (Persian) * fix profile tab bar in true black theme * fix m3 default button style closes sk22#697 * prettier role badges closes sk22#663 * fix translate button spacing closes sk22#655 * use m3 switches in dialogs closes sk22#653 * implement color palette switcher * fix color palettes being overwritten * add display and notification settings * clean up code * per-account single notification setting * add missing items to notification types * add prefix replies setting * add show replies/boosts and reply visibility * add load/see new posts settings * fix spectator mode missing spoiler padding * add a bunch of display settings * update fedinuke * add content type settings * add settings for local-onlu * add missing settings items * fix visibility button icon tint * hopefully fix some crashes * normalize padding above edit text * apparently, some people don't like pills closes sk22#706 * fix play button color closes sk22#705
This commit is contained in:
@@ -14,8 +14,6 @@ import org.parceler.Parcel;
|
||||
import org.parceler.ParcelConstructor;
|
||||
import org.parceler.ParcelProperty;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Parcel
|
||||
public class Attachment extends BaseModel{
|
||||
// @RequiredField
|
||||
@@ -135,6 +133,7 @@ public class Attachment extends BaseModel{
|
||||
public PointF focus;
|
||||
public SizeMetadata original;
|
||||
public SizeMetadata small;
|
||||
public ColorsMetadata colors;
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
@@ -146,6 +145,7 @@ public class Attachment extends BaseModel{
|
||||
", focus="+focus+
|
||||
", original="+original+
|
||||
", small="+small+
|
||||
", colors="+colors+
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -169,4 +169,20 @@ public class Attachment extends BaseModel{
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@Parcel
|
||||
public static class ColorsMetadata{
|
||||
public String background;
|
||||
public String foreground;
|
||||
public String accent;
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "ColorsMetadata{"+
|
||||
"background='"+background+'\''+
|
||||
", foreground='"+foreground+'\''+
|
||||
", accent='"+accent+'\''+
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,23 +18,22 @@ public enum ContentType {
|
||||
@SerializedName("text/bbcode")
|
||||
BBCODE, // akkoma
|
||||
@SerializedName("text/x.misskeymarkdown")
|
||||
MISSKEY_MARKDOWN; // akkoma/*key
|
||||
MISSKEY_MARKDOWN, // akkoma/*key
|
||||
@SerializedName("")
|
||||
UNSPECIFIED;
|
||||
|
||||
public static int getContentTypeRes(@Nullable ContentType contentType) {
|
||||
return contentType == null ? R.id.content_type_null : switch(contentType) {
|
||||
case PLAIN -> R.id.content_type_plain;
|
||||
case HTML -> R.id.content_type_html;
|
||||
case MARKDOWN -> R.id.content_type_markdown;
|
||||
case BBCODE -> R.id.content_type_bbcode;
|
||||
case MISSKEY_MARKDOWN -> R.id.content_type_misskey_markdown;
|
||||
public int getName() {
|
||||
return switch(this) {
|
||||
case PLAIN -> R.string.sk_content_type_plain;
|
||||
case HTML -> R.string.sk_content_type_html;
|
||||
case MARKDOWN -> R.string.sk_content_type_markdown;
|
||||
case BBCODE -> R.string.sk_content_type_bbcode;
|
||||
case MISSKEY_MARKDOWN -> R.string.sk_content_type_mfm;
|
||||
case UNSPECIFIED -> R.string.sk_content_type_unspecified;
|
||||
};
|
||||
}
|
||||
|
||||
public static void adaptMenuToInstance(Menu m, Instance i) {
|
||||
if (i.pleroma == null) {
|
||||
// memo: change this if glitch or another mastodon fork supports bbcode or mfm
|
||||
m.findItem(R.id.content_type_bbcode).setVisible(false);
|
||||
m.findItem(R.id.content_type_misskey_markdown).setVisible(false);
|
||||
}
|
||||
public boolean supportedByInstance(Instance i) {
|
||||
return i.isAkkoma() || (this!=BBCODE && this!=MISSKEY_MARKDOWN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,14 @@ public class Emoji extends BaseModel{
|
||||
*/
|
||||
public String category;
|
||||
|
||||
public Emoji() {}
|
||||
|
||||
public Emoji(String shortcode, String url, String staticUrl) {
|
||||
this.shortcode = shortcode.replaceAll(":", "");
|
||||
this.url = url;
|
||||
this.staticUrl = staticUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "Emoji{"+
|
||||
|
||||
@@ -1,62 +1,43 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.joinmastodon.android.api.ObjectValidationException;
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Parcel
|
||||
public class Filter extends BaseModel{
|
||||
@RequiredField
|
||||
public String id;
|
||||
public String phrase;
|
||||
|
||||
@RequiredField
|
||||
public String title;
|
||||
public transient EnumSet<FilterContext> context=EnumSet.noneOf(FilterContext.class);
|
||||
|
||||
@RequiredField
|
||||
public EnumSet<FilterContext> context;
|
||||
|
||||
public Instant expiresAt;
|
||||
public boolean irreversible;
|
||||
public boolean wholeWord;
|
||||
public FilterAction filterAction;
|
||||
|
||||
@SerializedName("context")
|
||||
protected List<FilterContext> _context;
|
||||
public List<FilterKeyword> keywords=new ArrayList<>();
|
||||
|
||||
private transient Pattern pattern;
|
||||
public List<FilterStatus> statuses=new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void postprocess() throws ObjectValidationException{
|
||||
super.postprocess();
|
||||
if(_context==null)
|
||||
throw new ObjectValidationException();
|
||||
for(FilterContext c:_context){
|
||||
if(c!=null)
|
||||
context.add(c);
|
||||
}
|
||||
for(FilterKeyword keyword:keywords)
|
||||
keyword.postprocess();
|
||||
for(FilterStatus status:statuses)
|
||||
status.postprocess();
|
||||
}
|
||||
|
||||
public boolean matches(CharSequence text){
|
||||
if(TextUtils.isEmpty(text))
|
||||
return false;
|
||||
if(pattern==null){
|
||||
if(wholeWord)
|
||||
pattern=Pattern.compile("\\b"+Pattern.quote(phrase)+"\\b", Pattern.CASE_INSENSITIVE);
|
||||
else
|
||||
pattern=Pattern.compile(Pattern.quote(phrase), Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
if (title == null) title = phrase;
|
||||
return pattern.matcher(text).find();
|
||||
}
|
||||
|
||||
public boolean matches(Status status){
|
||||
return matches(status.getContentStatus().getStrippedText());
|
||||
public boolean isActive(){
|
||||
return expiresAt==null || expiresAt.isAfter(Instant.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,31 +45,11 @@ public class Filter extends BaseModel{
|
||||
return "Filter{"+
|
||||
"id='"+id+'\''+
|
||||
", title='"+title+'\''+
|
||||
", phrase='"+phrase+'\''+
|
||||
", context="+context+
|
||||
", expiresAt="+expiresAt+
|
||||
", irreversible="+irreversible+
|
||||
", wholeWord="+wholeWord+
|
||||
", filterAction="+filterAction+
|
||||
", keywords="+keywords+
|
||||
", statuses="+statuses+
|
||||
'}';
|
||||
}
|
||||
|
||||
public enum FilterContext{
|
||||
@SerializedName("home")
|
||||
HOME,
|
||||
@SerializedName("notifications")
|
||||
NOTIFICATIONS,
|
||||
@SerializedName("public")
|
||||
PUBLIC,
|
||||
@SerializedName("thread")
|
||||
THREAD,
|
||||
@SerializedName("account")
|
||||
ACCOUNT
|
||||
}
|
||||
|
||||
public enum FilterAction{
|
||||
@SerializedName("hide")
|
||||
HIDE,
|
||||
@SerializedName("warn")
|
||||
WARN
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public enum FilterAction{
|
||||
@SerializedName("warn")
|
||||
WARN,
|
||||
@SerializedName("hide")
|
||||
HIDE
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
public enum FilterContext{
|
||||
@SerializedName("home")
|
||||
HOME,
|
||||
@SerializedName("notifications")
|
||||
NOTIFICATIONS,
|
||||
@SerializedName("public")
|
||||
PUBLIC,
|
||||
@SerializedName("thread")
|
||||
THREAD,
|
||||
@SerializedName("account")
|
||||
ACCOUNT;
|
||||
|
||||
@StringRes
|
||||
public int getDisplayNameRes(){
|
||||
return switch(this){
|
||||
case HOME -> R.string.filter_context_home_lists;
|
||||
case NOTIFICATIONS -> R.string.filter_context_notifications;
|
||||
case PUBLIC -> R.string.filter_context_public_timelines;
|
||||
case THREAD -> R.string.filter_context_threads_replies;
|
||||
case ACCOUNT -> R.string.filter_context_profiles;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
import org.joinmastodon.android.api.AllFieldsAreRequired;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
@AllFieldsAreRequired
|
||||
@Parcel
|
||||
public class FilterKeyword extends BaseModel{
|
||||
public String id;
|
||||
public String keyword;
|
||||
public boolean wholeWord;
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "FilterKeyword{"+
|
||||
"id='"+id+'\''+
|
||||
", keyword='"+keyword+'\''+
|
||||
", wholeWord="+wholeWord+
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,13 @@ package org.joinmastodon.android.model;
|
||||
import org.joinmastodon.android.api.ObjectValidationException;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Parcel
|
||||
public class FilterResult extends BaseModel {
|
||||
public Filter filter;
|
||||
public LegacyFilter filter;
|
||||
|
||||
public List<String> keywordMatches;
|
||||
|
||||
@Override
|
||||
public void postprocess() throws ObjectValidationException {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
import org.joinmastodon.android.api.AllFieldsAreRequired;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
@AllFieldsAreRequired
|
||||
@Parcel
|
||||
public class FilterStatus extends BaseModel{
|
||||
public String id;
|
||||
public String statusId;
|
||||
}
|
||||
@@ -6,13 +6,14 @@ import org.parceler.Parcel;
|
||||
import java.util.List;
|
||||
|
||||
@Parcel
|
||||
public class Hashtag extends BaseModel{
|
||||
public class Hashtag extends BaseModel implements DisplayItemsParent{
|
||||
@RequiredField
|
||||
public String name;
|
||||
@RequiredField
|
||||
public String url;
|
||||
public boolean following;
|
||||
public List<History> history;
|
||||
public int statusesCount;
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
@@ -21,6 +22,12 @@ public class Hashtag extends BaseModel{
|
||||
", url='"+url+'\''+
|
||||
", following="+following+
|
||||
", history="+history+
|
||||
", statusesCount="+statusesCount+
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID(){
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.joinmastodon.android.api.ObjectValidationException;
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Parcel
|
||||
public class LegacyFilter extends BaseModel{
|
||||
public String id;
|
||||
public String phrase;
|
||||
public String title;
|
||||
public transient EnumSet<FilterContext> context=EnumSet.noneOf(FilterContext.class);
|
||||
public Instant expiresAt;
|
||||
public boolean irreversible;
|
||||
public boolean wholeWord;
|
||||
|
||||
@SerializedName("context")
|
||||
protected List<FilterContext> _context;
|
||||
|
||||
public FilterAction filterAction;
|
||||
|
||||
public List<FilterKeyword> keywords=new ArrayList<>();
|
||||
|
||||
public List<FilterStatus> statuses=new ArrayList<>();
|
||||
|
||||
private transient Pattern pattern;
|
||||
|
||||
@Override
|
||||
public void postprocess() throws ObjectValidationException{
|
||||
super.postprocess();
|
||||
if(_context==null)
|
||||
throw new ObjectValidationException();
|
||||
for(FilterContext c:_context){
|
||||
if(c!=null)
|
||||
context.add(c);
|
||||
}
|
||||
for(FilterKeyword keyword:keywords)
|
||||
keyword.postprocess();
|
||||
for(FilterStatus status:statuses)
|
||||
status.postprocess();
|
||||
}
|
||||
|
||||
public boolean matches(CharSequence text){
|
||||
if(TextUtils.isEmpty(text))
|
||||
return false;
|
||||
if(pattern==null){
|
||||
if(wholeWord)
|
||||
pattern=Pattern.compile("\\b"+Pattern.quote(phrase)+"\\b", Pattern.CASE_INSENSITIVE);
|
||||
else
|
||||
pattern=Pattern.compile(Pattern.quote(phrase), Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
if (title == null) title = phrase;
|
||||
return pattern.matcher(text).find();
|
||||
}
|
||||
|
||||
public boolean matches(Status status){
|
||||
return matches(status.getContentStatus().getStrippedText());
|
||||
}
|
||||
|
||||
public boolean isActive(){
|
||||
return expiresAt==null || expiresAt.isAfter(Instant.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "Filter{"+
|
||||
"id='"+id+'\''+
|
||||
", title='"+title+'\''+
|
||||
", phrase='"+phrase+'\''+
|
||||
", context="+context+
|
||||
", expiresAt="+expiresAt+
|
||||
", irreversible="+irreversible+
|
||||
", wholeWord="+wholeWord+
|
||||
", filterAction="+filterAction+
|
||||
", keywords="+keywords+
|
||||
", statuses="+statuses+
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class ParsedAccount{
|
||||
public Account account;
|
||||
public CharSequence parsedName, parsedBio;
|
||||
public CustomEmojiHelper emojiHelper;
|
||||
public ImageLoaderRequest avatarRequest;
|
||||
|
||||
public ParsedAccount(Account account, String accountID){
|
||||
this.account=account;
|
||||
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
|
||||
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
||||
|
||||
emojiHelper=new CustomEmojiHelper();
|
||||
SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName);
|
||||
ssb.append(parsedBio);
|
||||
emojiHelper.setText(ssb);
|
||||
|
||||
avatarRequest=new UrlImageLoaderRequest(GlobalUserPreferences.playGifs ? account.avatar : account.avatarStatic, V.dp(40), V.dp(40));
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ public class Poll extends BaseModel{
|
||||
@RequiredField
|
||||
public String id;
|
||||
public Instant expiresAt;
|
||||
protected boolean expired;
|
||||
public boolean expired;
|
||||
public boolean multiple;
|
||||
public int votersCount;
|
||||
public int votesCount;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
@Parcel
|
||||
public class Relationship extends BaseModel{
|
||||
@RequiredField
|
||||
public String id;
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.joinmastodon.android.model;
|
||||
|
||||
import org.joinmastodon.android.api.ObjectValidationException;
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
import org.joinmastodon.android.model.viewmodel.AccountViewModel;
|
||||
|
||||
public class SearchResult extends BaseModel implements DisplayItemsParent{
|
||||
public Account account;
|
||||
@@ -11,6 +12,7 @@ public class SearchResult extends BaseModel implements DisplayItemsParent{
|
||||
public Type type;
|
||||
|
||||
public transient String id;
|
||||
public transient boolean firstInSection;
|
||||
|
||||
public SearchResult(){}
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@ package org.joinmastodon.android.model;
|
||||
import static org.joinmastodon.android.api.MastodonAPIController.gson;
|
||||
import static org.joinmastodon.android.api.MastodonAPIController.gsonWithoutDeserializer;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
@@ -50,8 +54,6 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
||||
public long favouritesCount;
|
||||
public long repliesCount;
|
||||
public Instant editedAt;
|
||||
// might not be provided (by older mastodon servers),
|
||||
// so megalodon will use the locally cached filters if filtered == null
|
||||
public List<FilterResult> filtered;
|
||||
|
||||
public String url;
|
||||
@@ -74,17 +76,17 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
||||
|
||||
public transient boolean filterRevealed;
|
||||
public transient boolean spoilerRevealed;
|
||||
public transient boolean sensitiveRevealed;
|
||||
public transient boolean textExpanded, textExpandable;
|
||||
public transient boolean hasGapAfter;
|
||||
public transient TranslatedStatus translation;
|
||||
public transient boolean translationShown;
|
||||
private transient String strippedText;
|
||||
|
||||
public Status(){}
|
||||
|
||||
@Override
|
||||
public void postprocess() throws ObjectValidationException{
|
||||
if(spoilerText!=null && !spoilerText.isEmpty() && !sensitive)
|
||||
sensitive=true;
|
||||
|
||||
super.postprocess();
|
||||
if(application!=null)
|
||||
application.postprocess();
|
||||
@@ -105,10 +107,12 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
||||
if(reblog!=null)
|
||||
reblog.postprocess();
|
||||
if(filtered!=null)
|
||||
for(FilterResult fr : filtered)
|
||||
for(FilterResult fr:filtered)
|
||||
fr.postprocess();
|
||||
|
||||
spoilerRevealed=GlobalUserPreferences.alwaysExpandContentWarnings || !sensitive;
|
||||
if (!TextUtils.isEmpty(spoilerText)) sensitive = true;
|
||||
spoilerRevealed=TextUtils.isEmpty(spoilerText);
|
||||
sensitiveRevealed=!sensitive;
|
||||
if (visibility.equals(StatusPrivacy.LOCAL)) localOnly = true;
|
||||
}
|
||||
|
||||
@@ -131,6 +135,7 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
||||
", reblogsCount="+reblogsCount+
|
||||
", favouritesCount="+favouritesCount+
|
||||
", repliesCount="+repliesCount+
|
||||
", editedAt="+editedAt+
|
||||
", url='"+url+'\''+
|
||||
", inReplyToId='"+inReplyToId+'\''+
|
||||
", inReplyToAccountId='"+inReplyToAccountId+'\''+
|
||||
@@ -139,11 +144,15 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
||||
", card="+card+
|
||||
", language='"+language+'\''+
|
||||
", text='"+text+'\''+
|
||||
", filtered="+filtered+
|
||||
", favourited="+favourited+
|
||||
", reblogged="+reblogged+
|
||||
", muted="+muted+
|
||||
", bookmarked="+bookmarked+
|
||||
", pinned="+pinned+
|
||||
", spoilerRevealed="+spoilerRevealed+
|
||||
", hasGapAfter="+hasGapAfter+
|
||||
", strippedText='"+strippedText+'\''+
|
||||
'}';
|
||||
}
|
||||
|
||||
@@ -172,6 +181,12 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
||||
return strippedText;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Status clone(){
|
||||
return (Status) super.clone();
|
||||
}
|
||||
|
||||
public boolean isReblogPermitted(String accountID){
|
||||
return visibility.isReblogPermitted(account.id.equals(
|
||||
AccountSessionManager.getInstance().getAccount(accountID).self.id
|
||||
@@ -189,6 +204,7 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
||||
s.mentions = List.of();
|
||||
s.tags = List.of();
|
||||
s.emojis = List.of();
|
||||
s.filtered = List.of();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -337,20 +337,20 @@ public class TimelineDefinition {
|
||||
}
|
||||
};
|
||||
|
||||
public static List<TimelineDefinition> getDefaultTimelines(String accountId) {
|
||||
public static ArrayList<TimelineDefinition> getDefaultTimelines(String accountId) {
|
||||
AccountSession session = AccountSessionManager.getInstance().getAccount(accountId);
|
||||
return DEFAULT_TIMELINES.stream()
|
||||
.filter(tl -> tl.isCompatible(session) && tl.wantsDefault(session))
|
||||
.map(TimelineDefinition::copy)
|
||||
.collect(Collectors.toList());
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
public static List<TimelineDefinition> getAllTimelines(String accountId) {
|
||||
public static ArrayList<TimelineDefinition> getAllTimelines(String accountId) {
|
||||
AccountSession session = AccountSessionManager.getInstance().getAccount(accountId);
|
||||
return ALL_TIMELINES.stream()
|
||||
.filter(tl -> tl.isCompatible(session))
|
||||
.map(TimelineDefinition::copy)
|
||||
.collect(Collectors.toList());
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
private static final List<TimelineDefinition> DEFAULT_TIMELINES = List.of(
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
public class TimelineMarkers{
|
||||
public Marker home, notifications;
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "TimelineMarkers{"+
|
||||
"home="+home+
|
||||
", notifications="+notifications+
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.joinmastodon.android.model.catalog;
|
||||
|
||||
import org.joinmastodon.android.api.AllFieldsAreRequired;
|
||||
import org.joinmastodon.android.model.BaseModel;
|
||||
|
||||
@AllFieldsAreRequired
|
||||
public class CatalogDefaultInstance extends BaseModel{
|
||||
public String domain;
|
||||
public float weight;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.joinmastodon.android.model.viewmodel;
|
||||
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.AccountField;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class AccountViewModel{
|
||||
public final Account account;
|
||||
public final ImageLoaderRequest avaRequest;
|
||||
public final CustomEmojiHelper emojiHelper;
|
||||
public final CharSequence parsedName, parsedBio;
|
||||
public final String verifiedLink;
|
||||
|
||||
public AccountViewModel(Account account, String accountID){
|
||||
this.account=account;
|
||||
avaRequest=new UrlImageLoaderRequest(GlobalUserPreferences.playGifs ? account.avatar : account.avatarStatic, V.dp(50), V.dp(50));
|
||||
emojiHelper=new CustomEmojiHelper();
|
||||
if(AccountSessionManager.get(accountID).getLocalPreferences().customEmojiInNames)
|
||||
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
|
||||
else
|
||||
parsedName=account.displayName;
|
||||
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
||||
SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName);
|
||||
ssb.append(parsedBio);
|
||||
emojiHelper.setText(ssb);
|
||||
String verifiedLink=null;
|
||||
for(AccountField fld:account.fields){
|
||||
if(fld.verifiedAt!=null){
|
||||
verifiedLink=HtmlParser.stripAndRemoveInvisibleSpans(fld.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.verifiedLink=verifiedLink;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.joinmastodon.android.model.viewmodel;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.joinmastodon.android.model.Card;
|
||||
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class CardViewModel{
|
||||
public final Card card;
|
||||
public final ImageLoaderRequest imageRequest;
|
||||
|
||||
public CardViewModel(Card card, int width, int height){
|
||||
this.card=card;
|
||||
this.imageRequest=TextUtils.isEmpty(card.image) ? null : new UrlImageLoaderRequest(card.image, V.dp(width), V.dp(height));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.joinmastodon.android.model.viewmodel;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CheckableListItem<T> extends ListItem<T>{
|
||||
public Style style;
|
||||
public boolean checked;
|
||||
public Consumer<Boolean> checkedChangeListener;
|
||||
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick, T parentObject, boolean dividerAfter){
|
||||
super(title, subtitle, iconRes, onClick, parentObject, 0, dividerAfter);
|
||||
this.style=style;
|
||||
this.checked=checked;
|
||||
}
|
||||
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Runnable onClick){
|
||||
this(title, subtitle, style, checked, 0, onClick, null, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Runnable onClick, T parentObject){
|
||||
this(title, subtitle, style, checked, 0, onClick, parentObject, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick){
|
||||
this(title, subtitle, style, checked, iconRes, onClick, null, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick, T parentObject){
|
||||
this(title, subtitle, style, checked, iconRes, onClick, parentObject, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Runnable onClick){
|
||||
this(titleRes, subtitleRes, style, checked, 0, onClick, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Runnable onClick, boolean dividerAfter){
|
||||
this(titleRes, subtitleRes, style, checked, 0, onClick, dividerAfter);
|
||||
}
|
||||
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Runnable onClick){
|
||||
this(titleRes, subtitleRes, style, checked, iconRes, onClick, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Runnable onClick, boolean dividerAfter){
|
||||
super(titleRes, subtitleRes, iconRes, onClick, 0, dividerAfter);
|
||||
this.style=style;
|
||||
this.checked=checked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(){
|
||||
return switch(style){
|
||||
case CHECKBOX -> R.id.list_item_checkbox;
|
||||
case RADIO -> R.id.list_item_radio;
|
||||
case SWITCH -> R.id.list_item_switch;
|
||||
};
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked){
|
||||
this.checked=checked;
|
||||
}
|
||||
|
||||
public void toggle(){
|
||||
checked=!checked;
|
||||
}
|
||||
|
||||
public enum Style{
|
||||
CHECKBOX,
|
||||
RADIO,
|
||||
SWITCH
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.joinmastodon.android.model.viewmodel;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
public class ListItem<T>{
|
||||
public String title;
|
||||
public String subtitle;
|
||||
@StringRes
|
||||
public int titleRes;
|
||||
@StringRes
|
||||
public int subtitleRes;
|
||||
@DrawableRes
|
||||
public int iconRes;
|
||||
public int colorOverrideAttr;
|
||||
public boolean dividerAfter;
|
||||
public Runnable onClick;
|
||||
public boolean isEnabled=true;
|
||||
public T parentObject;
|
||||
|
||||
public ListItem(String title, String subtitle, int iconRes, Runnable onClick, T parentObject, int colorOverrideAttr, boolean dividerAfter){
|
||||
this.title=title;
|
||||
this.subtitle=subtitle;
|
||||
this.iconRes=iconRes;
|
||||
this.colorOverrideAttr=colorOverrideAttr;
|
||||
this.dividerAfter=dividerAfter;
|
||||
this.onClick=onClick;
|
||||
this.parentObject=parentObject;
|
||||
if(onClick==null)
|
||||
isEnabled=false;
|
||||
}
|
||||
|
||||
public ListItem(String title, String subtitle, Runnable onClick){
|
||||
this(title, subtitle, 0, onClick, null, 0, false);
|
||||
}
|
||||
|
||||
public ListItem(String title, String subtitle, Runnable onClick, T parentObject){
|
||||
this(title, subtitle, 0, onClick, parentObject, 0, false);
|
||||
}
|
||||
|
||||
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick){
|
||||
this(title, subtitle, iconRes, onClick, null, 0, false);
|
||||
}
|
||||
|
||||
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick, boolean dividerAfter){
|
||||
this(title, subtitle, iconRes, onClick, null, 0, dividerAfter);
|
||||
}
|
||||
|
||||
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick, T parentObject){
|
||||
this(title, subtitle, iconRes, onClick, parentObject, 0, false);
|
||||
}
|
||||
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Runnable onClick){
|
||||
this(null, null, 0, onClick, null, 0, false);
|
||||
this.titleRes=titleRes;
|
||||
this.subtitleRes=subtitleRes;
|
||||
}
|
||||
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Runnable onClick, int colorOverrideAttr, boolean dividerAfter){
|
||||
this(null, null, 0, onClick, null, colorOverrideAttr, dividerAfter);
|
||||
this.titleRes=titleRes;
|
||||
this.subtitleRes=subtitleRes;
|
||||
}
|
||||
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Runnable onClick){
|
||||
this(null, null, iconRes, onClick, null, 0, false);
|
||||
this.titleRes=titleRes;
|
||||
this.subtitleRes=subtitleRes;
|
||||
}
|
||||
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Runnable onClick, int colorOverrideAttr, boolean dividerAfter){
|
||||
this(null, null, iconRes, onClick, null, colorOverrideAttr, dividerAfter);
|
||||
this.titleRes=titleRes;
|
||||
this.subtitleRes=subtitleRes;
|
||||
}
|
||||
|
||||
public int getItemViewType(){
|
||||
return colorOverrideAttr==0 ? R.id.list_item_simple : R.id.list_item_simple_tinted;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.joinmastodon.android.model.viewmodel;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.model.Hashtag;
|
||||
import org.joinmastodon.android.model.SearchResult;
|
||||
|
||||
public class SearchResultViewModel{
|
||||
public SearchResult result;
|
||||
public AccountViewModel account;
|
||||
public ListItem<Hashtag> hashtagItem;
|
||||
|
||||
public SearchResultViewModel(SearchResult result, String accountID, boolean isRecents){
|
||||
this.result=result;
|
||||
switch(result.type){
|
||||
case ACCOUNT -> account=new AccountViewModel(result.account, accountID);
|
||||
case HASHTAG -> {
|
||||
hashtagItem=new ListItem<>((isRecents ? "#" : "")+result.hashtag.name, null, isRecents ? R.drawable.ic_fluent_history_24_regular : R.drawable.ic_fluent_number_symbol_24_regular, null, result.hashtag);
|
||||
hashtagItem.isEnabled=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user