Compare commits

..

26 commits

Author SHA1 Message Date
claleb
56cd4f38eb
Translated using Weblate (German)
Currently translated at 100.0% (1085 of 1085 strings)

Co-authored-by: claleb <weblate@claleb.de>
Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/de/
Translation: Fedilab/Strings
2023-02-08 07:37:08 +01:00
Lukáš Jelínek
abc301b7dd
Translated using Weblate (Czech)
Currently translated at 99.9% (1084 of 1085 strings)

Co-authored-by: Lukáš Jelínek <devel@aiken.cz>
Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/cs/
Translation: Fedilab/Strings
2023-02-08 07:37:07 +01:00
Thomas
a3a3d9350e Fix a bug with media not available 2023-02-07 16:01:05 +01:00
Thomas
34a8a4ee85 Merge remote-tracking branch 'origin/develop' into develop 2023-02-07 15:34:38 +01:00
Thomas
70783bb532 Fix a crash when composing 2023-02-07 15:34:14 +01:00
Thomas
413d11b3c3 Height of media depends of screen size 2023-02-07 15:29:58 +01:00
Poesty Li
8686d16db6
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (1085 of 1085 strings)

Co-authored-by: Poesty Li <poesty7450@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/zh_Hans/
Translation: Fedilab/Strings
2023-02-06 18:50:02 +01:00
Oğuz Ersen
4106802f4a
Translated using Weblate (Turkish)
Currently translated at 100.0% (1085 of 1085 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/tr/
Translation: Fedilab/Strings
2023-02-06 18:50:02 +01:00
Thomas
c2e15c2bfb Add blurhash when available 2023-02-06 18:16:53 +01:00
Thomas
37bc798e38 Fix some crashes 2023-02-06 17:42:00 +01:00
Thomas
5c73717373 Fix some crashes 2023-02-06 14:48:45 +01:00
Thomas
4837afcfb0 Merge pull request 'Fix unpin_tag string used in place of pin_tag.' (#783) from trem/Fedilab:develop into develop
Reviewed-on: https://codeberg.org/tom79/Fedilab/pulls/783
2023-02-06 09:27:56 +00:00
Thomas
810b2e9864 Fix issue #782 - Overlapped texts with "About my instance" 2023-02-06 10:16:45 +01:00
Thomas
2fcb02ea4f Fix issue #780 - Add descriptions to images for drafts 2023-02-06 09:48:37 +01:00
Thomas
3db9d22e48 Fix issue #779 - Focus view for accessibility with visibility when composing 2023-02-06 09:41:53 +01:00
Thomas
f817fd0797 Merge remote-tracking branch 'origin/develop' into develop 2023-02-06 09:34:02 +01:00
Thomas
8bbac74334 Fix issue #778 - Add description to remove button for fields. 2023-02-06 09:33:56 +01:00
SevicheCC
fd13861603
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (1080 of 1080 strings)

Co-authored-by: SevicheCC <me@seviche.cc>
Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/zh_Hans/
Translation: Fedilab/Strings
2023-02-06 09:30:25 +01:00
Poesty Li
8177ffd4f3
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (1080 of 1080 strings)

Co-authored-by: Poesty Li <poesty7450@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/zh_Hans/
Translation: Fedilab/Strings
2023-02-06 09:30:25 +01:00
Oğuz Ersen
82d85168d5
Translated using Weblate (Turkish)
Currently translated at 100.0% (1080 of 1080 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/tr/
Translation: Fedilab/Strings
2023-02-06 09:30:25 +01:00
Ajeje Brazorf
4721b185aa
Translated using Weblate (Sardinian)
Currently translated at 99.2% (1072 of 1080 strings)

Co-authored-by: Ajeje Brazorf <lmelonimamo@yahoo.it>
Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/sc/
Translation: Fedilab/Strings
2023-02-06 09:30:25 +01:00
claleb
8e9cb798b7
Translated using Weblate (German)
Currently translated at 100.0% (1080 of 1080 strings)

Co-authored-by: claleb <weblate@claleb.de>
Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/de/
Translation: Fedilab/Strings
2023-02-06 09:30:25 +01:00
Lukáš Jelínek
e204faed0e
Translated using Weblate (Czech)
Currently translated at 99.9% (1079 of 1080 strings)

Co-authored-by: Lukáš Jelínek <devel@aiken.cz>
Translate-URL: https://hosted.weblate.org/projects/fedilab/strings/cs/
Translation: Fedilab/Strings
2023-02-06 09:30:25 +01:00
Thomas
d78235cb11 Fix issue #777 2023-02-06 09:30:16 +01:00
Thomas
1af2ba3822 Fix issue #776 2023-02-06 09:24:15 +01:00
trem
ad28ddd6b2 Fix unpin_tag string used in place of pin_tag. 2023-02-05 22:02:12 +01:00
24 changed files with 306 additions and 226 deletions

View file

@ -355,7 +355,7 @@ public class HashTagActivity extends BaseActivity {
pin.setIcon(R.drawable.tag_pin_off);
pin.setTitle(getString(R.string.unpin_tag));
} else {
pin.setTitle(getString(R.string.unpin_tag));
pin.setTitle(getString(R.string.pin_tag));
pin.setIcon(R.drawable.tag_pin);
}
} else {

View file

@ -318,18 +318,4 @@ public interface MastodonStatusesService {
@Header("Authorization") String token,
@Path("id") String id
);
@POST("statuses/{id}/react/{name}")
Call<Void> addReaction(
@Header("Authorization") String app_token,
@Path("id") String id,
@Path("name") String name
);
@POST("statuses/{id}/unreact/{name}")
Call<Void> removeReaction(
@Header("Authorization") String app_token,
@Path("id") String id,
@Path("name") String name
);
}

View file

@ -109,8 +109,6 @@ public class Status implements Serializable, Cloneable {
public boolean cached = false;
@SerializedName("is_maths")
public Boolean isMaths;
@SerializedName("reactions")
public List<Reaction> reactions;
public Attachment art_attachment;
public boolean isExpended = false;

View file

@ -0,0 +1,127 @@
package app.fedilab.android.mastodon.helper
import android.graphics.Bitmap
import android.graphics.Color
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.pow
import kotlin.math.withSign
class BlurHashDecoder {
fun decode(blurHash: String?, width: Int, height: Int, punch: Float = 1f): Bitmap? {
require(width > 0) { "Width must be greater than zero" }
require(height > 0) { "height must be greater than zero" }
if (blurHash == null || blurHash.length < 6) {
return null
}
val numCompEnc = decode83(blurHash, 0, 1)
val numCompX = (numCompEnc % 9) + 1
val numCompY = (numCompEnc / 9) + 1
if (blurHash.length != 4 + 2 * numCompX * numCompY) {
return null
}
val maxAcEnc = decode83(blurHash, 1, 2)
val maxAc = (maxAcEnc + 1) / 166f
val colors = Array(numCompX * numCompY) { i ->
if (i == 0) {
val colorEnc = decode83(blurHash, 2, 6)
decodeDc(colorEnc)
} else {
val from = 4 + i * 2
val colorEnc = decode83(blurHash, from, from + 2)
decodeAc(colorEnc, maxAc * punch)
}
}
return composeBitmap(width, height, numCompX, numCompY, colors)
}
private fun decode83(str: String, from: Int = 0, to: Int = str.length): Int {
var result = 0
for (i in from until to) {
val index = charMap[str[i]] ?: -1
if (index != -1) {
result = result * 83 + index
}
}
return result
}
private fun decodeDc(colorEnc: Int): FloatArray {
val r = colorEnc shr 16
val g = (colorEnc shr 8) and 255
val b = colorEnc and 255
return floatArrayOf(srgbToLinear(r), srgbToLinear(g), srgbToLinear(b))
}
private fun srgbToLinear(colorEnc: Int): Float {
val v = colorEnc / 255f
return if (v <= 0.04045f) {
(v / 12.92f)
} else {
((v + 0.055f) / 1.055f).pow(2.4f)
}
}
private fun decodeAc(value: Int, maxAc: Float): FloatArray {
val r = value / (19 * 19)
val g = (value / 19) % 19
val b = value % 19
return floatArrayOf(
signedPow2((r - 9) / 9.0f) * maxAc,
signedPow2((g - 9) / 9.0f) * maxAc,
signedPow2((b - 9) / 9.0f) * maxAc
)
}
private fun signedPow2(value: Float) = value.pow(2f).withSign(value)
private fun composeBitmap(
width: Int,
height: Int,
numCompX: Int,
numCompY: Int,
colors: Array<FloatArray>
): Bitmap {
val imageArray = IntArray(width * height)
for (y in 0 until height) {
for (x in 0 until width) {
var r = 0f
var g = 0f
var b = 0f
for (j in 0 until numCompY) {
for (i in 0 until numCompX) {
val basis = (cos(PI * x * i / width) * cos(PI * y * j / height)).toFloat()
val color = colors[j * numCompX + i]
r += color[0] * basis
g += color[1] * basis
b += color[2] * basis
}
}
imageArray[x + width * y] =
Color.rgb(linearToSrgb(r), linearToSrgb(g), linearToSrgb(b))
}
}
return Bitmap.createBitmap(imageArray, width, height, Bitmap.Config.ARGB_8888)
}
private fun linearToSrgb(value: Float): Int {
val v = value.coerceIn(0f, 1f)
return if (v <= 0.0031308f) {
(v * 12.92f * 255f + 0.5f).toInt()
} else {
((1.055f * v.pow(1 / 2.4f) - 0.055f) * 255 + 0.5f).toInt()
}
}
private val charMap = listOf(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '#', '$', '%', '*', '+', ',',
'-', '.', ':', ';', '=', '?', '@', '[', ']', '^', '_', '{', '|', '}', '~'
)
.mapIndexed { i, c -> c to i }
.toMap()
}

View file

@ -130,8 +130,12 @@ public class MastodonHelper {
* @return Pagination
*/
public static Pagination getPagination(Headers headers) {
String link = headers.get("Link");
Pagination pagination = new Pagination();
if (headers == null) {
return pagination;
}
String link = headers.get("Link");
if (link != null) {
Pattern patternMaxId = Pattern.compile("max_id=([0-9a-zA-Z]+).*");
Matcher matcherMaxId = patternMaxId.matcher(link);

View file

@ -49,6 +49,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
@ -1506,6 +1507,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
holder.binding.buttonCloseAttachmentPanel.setOnClickListener(v -> holder.binding.attachmentChoicesPanel.setVisibility(View.GONE));
holder.binding.buttonVisibility.setOnClickListener(v -> {
holder.binding.visibilityPanel.setVisibility(View.VISIBLE);
holder.binding.visibilityGroup.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
holder.binding.buttonVisibility.setChecked(false);
});
holder.binding.buttonCloseVisibilityPanel.setOnClickListener(v -> holder.binding.visibilityPanel.setVisibility(View.GONE));
@ -1587,7 +1589,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
if (!mentionsAtTop) {
holder.binding.content.setSelection(statusDraft.cursorPosition);
} else {
if (capitalize && !statusDraft.text.endsWith("\n")) {
if (capitalize && statusDraft.text != null && !statusDraft.text.endsWith("\n")) {
statusDraft.text += "\n";
holder.binding.content.setText(statusDraft.text);
}

View file

@ -34,7 +34,6 @@ import app.fedilab.android.mastodon.client.entities.api.Reaction;
import app.fedilab.android.mastodon.helper.Helper;
import app.fedilab.android.mastodon.helper.ThemeHelper;
import app.fedilab.android.mastodon.viewmodel.mastodon.AnnouncementsVM;
import app.fedilab.android.mastodon.viewmodel.mastodon.StatusesVM;
import app.fedilab.android.mastodon.viewmodel.pleroma.ActionsVM;
@ -47,29 +46,18 @@ public class ReactionAdapter extends RecyclerView.Adapter<ReactionAdapter.Reacti
private final List<Reaction> reactions;
private final String announcementId;
private final boolean statusReaction;
private final boolean isPleroma;
private Context context;
ReactionAdapter(String announcementId, List<Reaction> reactions, boolean statusReaction, boolean isPleroma) {
this.reactions = reactions;
this.announcementId = announcementId;
this.statusReaction = statusReaction;
this.isPleroma = isPleroma;
}
ReactionAdapter(String announcementId, List<Reaction> reactions, boolean statusReaction) {
this.reactions = reactions;
this.announcementId = announcementId;
this.statusReaction = statusReaction;
this.isPleroma = true;
}
ReactionAdapter(String announcementId, List<Reaction> reactions) {
this.reactions = reactions;
this.announcementId = announcementId;
this.statusReaction = false;
this.isPleroma = true;
}
@NonNull
@ -113,7 +101,7 @@ public class ReactionAdapter extends RecyclerView.Adapter<ReactionAdapter.Reacti
}
notifyItemChanged(position);
});
} else if (isPleroma) {
} else {
ActionsVM actionVM = new ViewModelProvider((ViewModelStoreOwner) context).get(ActionsVM.class);
holder.binding.reactionContainer.setOnClickListener(v -> {
if (reaction.me) {
@ -127,20 +115,6 @@ public class ReactionAdapter extends RecyclerView.Adapter<ReactionAdapter.Reacti
}
notifyItemChanged(position);
});
} else {
StatusesVM statusesVM = new ViewModelProvider((ViewModelStoreOwner) context).get(StatusesVM.class);
holder.binding.reactionContainer.setOnClickListener(v -> {
if (reaction.me) {
statusesVM.removeReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, announcementId, reaction.name);
reaction.me = false;
reaction.count -= 1;
} else {
statusesVM.addReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, announcementId, reaction.name);
reaction.me = true;
reaction.count += 1;
}
notifyItemChanged(position);
});
}
}

View file

@ -39,8 +39,10 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
@ -50,7 +52,6 @@ import android.os.Looper;
import android.text.Html;
import android.text.SpannableString;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@ -139,6 +140,7 @@ import app.fedilab.android.mastodon.client.entities.app.StatusCache;
import app.fedilab.android.mastodon.client.entities.app.StatusDraft;
import app.fedilab.android.mastodon.client.entities.app.Timeline;
import app.fedilab.android.mastodon.exception.DBException;
import app.fedilab.android.mastodon.helper.BlurHashDecoder;
import app.fedilab.android.mastodon.helper.CrossActionHelper;
import app.fedilab.android.mastodon.helper.GlideApp;
import app.fedilab.android.mastodon.helper.GlideFocus;
@ -520,7 +522,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
holder.binding.quotedMessage.cardviewContainer.setVisibility(View.GONE);
}
if (currentAccount != null && currentAccount.api == Account.API.PLEROMA || status.reactions != null) {
if (currentAccount != null && currentAccount.api == Account.API.PLEROMA) {
if (status.pleroma != null && status.pleroma.emoji_reactions != null && status.pleroma.emoji_reactions.size() > 0) {
holder.binding.layoutReactions.getRoot().setVisibility(View.VISIBLE);
ReactionAdapter reactionAdapter = new ReactionAdapter(status.id, status.pleroma.emoji_reactions, true);
@ -528,13 +530,6 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
LinearLayoutManager layoutManager
= new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
holder.binding.layoutReactions.reactionsView.setLayoutManager(layoutManager);
} else if (status.reactions != null && status.reactions.size() > 0) {
holder.binding.layoutReactions.getRoot().setVisibility(View.VISIBLE);
ReactionAdapter reactionAdapter = new ReactionAdapter(status.id, status.reactions, true, false);
holder.binding.layoutReactions.reactionsView.setAdapter(reactionAdapter);
LinearLayoutManager layoutManager
= new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
holder.binding.layoutReactions.reactionsView.setLayoutManager(layoutManager);
} else {
holder.binding.layoutReactions.getRoot().setVisibility(View.GONE);
holder.binding.layoutReactions.reactionsView.setAdapter(null);
@ -547,7 +542,9 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
}).setOnEmojiClickListener((emoji, imageView) -> {
String emojiStr = imageView.getUnicode();
boolean alreadyAdded = false;
if (status.pleroma != null && status.pleroma.emoji_reactions != null) {
if (status.pleroma == null || status.pleroma.emoji_reactions == null) {
return;
}
for (Reaction reaction : status.pleroma.emoji_reactions) {
if (reaction.name.compareTo(emojiStr) == 0 && reaction.me) {
alreadyAdded = true;
@ -573,32 +570,6 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
} else {
actionVM.addReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
}
} else if (status.reactions != null) {
for (Reaction reaction : status.reactions) {
if (reaction.name.compareTo(emojiStr) == 0 && reaction.me) {
alreadyAdded = true;
reaction.count = (reaction.count - 1);
if (reaction.count == 0) {
status.reactions.remove(reaction);
}
adapter.notifyItemChanged(holder.getBindingAdapterPosition());
break;
}
}
if (!alreadyAdded) {
Reaction reaction = new Reaction();
reaction.me = true;
reaction.count = 1;
reaction.name = emojiStr;
status.reactions.add(0, reaction);
adapter.notifyItemChanged(holder.getBindingAdapterPosition());
}
if (alreadyAdded) {
statusesVM.removeReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
} else {
statusesVM.addReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
}
}
})
.build(holder.binding.layoutReactions.fakeEdittext);
emojiPopup.toggle();
@ -623,7 +594,6 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
String url = emojis.get(BaseMainActivity.currentInstance).get(index).url;
String static_url = emojis.get(BaseMainActivity.currentInstance).get(index).static_url;
boolean alreadyAdded = false;
if (status.pleroma != null && status.pleroma.emoji_reactions != null) {
for (Reaction reaction : status.pleroma.emoji_reactions) {
if (reaction.name.compareTo(emojiStr) == 0 && reaction.me) {
alreadyAdded = true;
@ -651,34 +621,6 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
} else {
actionsVM.addReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
}
} else if (status.reactions != null) {
for (Reaction reaction : status.reactions) {
if (reaction.name.compareTo(emojiStr) == 0 && reaction.me) {
alreadyAdded = true;
reaction.count = (reaction.count - 1);
if (reaction.count == 0) {
status.reactions.remove(reaction);
}
adapter.notifyItemChanged(holder.getBindingAdapterPosition());
break;
}
}
if (!alreadyAdded) {
Reaction reaction = new Reaction();
reaction.me = true;
reaction.count = 1;
reaction.name = emojiStr;
reaction.url = url;
reaction.static_url = static_url;
status.reactions.add(0, reaction);
adapter.notifyItemChanged(holder.getBindingAdapterPosition());
}
if (alreadyAdded) {
statusesVM.removeReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
} else {
statusesVM.addReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
}
}
});
gridView.setPadding(paddingDp, paddingDp, paddingDp, paddingDp);
builder.setView(gridView);
@ -1172,15 +1114,23 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
}
int ressource = R.drawable.ic_baseline_public_24;
holder.binding.visibility.setContentDescription(context.getString(R.string.v_public));
holder.binding.visibilitySmall.setContentDescription(context.getString(R.string.v_public));
switch (status.visibility) {
case "unlisted":
holder.binding.visibility.setContentDescription(context.getString(R.string.v_unlisted));
holder.binding.visibilitySmall.setContentDescription(context.getString(R.string.v_unlisted));
ressource = R.drawable.ic_baseline_lock_open_24;
break;
case "private":
ressource = R.drawable.ic_baseline_lock_24;
holder.binding.visibility.setContentDescription(context.getString(R.string.v_private));
holder.binding.visibilitySmall.setContentDescription(context.getString(R.string.v_private));
break;
case "direct":
ressource = R.drawable.ic_baseline_mail_24;
holder.binding.visibility.setContentDescription(context.getString(R.string.v_direct));
holder.binding.visibilitySmall.setContentDescription(context.getString(R.string.v_direct));
break;
}
@ -1338,6 +1288,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
holder.binding.actionButtonBoost.setVisibility(View.GONE);
break;
}
//--- MAIN CONTENT ---
holder.binding.statusContent.setText(
statusToDeal.getSpanContent(context,
@ -2189,7 +2140,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
//We hide the button
status.isFetchMore = false;
String fromId;
if (status.positionFetchMore == Status.PositionFetchMore.TOP) {
if (status.positionFetchMore == Status.PositionFetchMore.TOP || holder.getBindingAdapterPosition() == 0) {
fromId = statusList.get(holder.getBindingAdapterPosition()).id;
} else {
fromId = statusList.get(holder.getBindingAdapterPosition() - 1).id;
@ -2210,7 +2161,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
statusIdMin = status.id;
}
}
if (status.positionFetchMore == Status.PositionFetchMore.TOP) {
if (status.positionFetchMore == Status.PositionFetchMore.TOP || holder.getBindingAdapterPosition() == 0) {
statusIdMax = statusList.get(holder.getBindingAdapterPosition()).id;
} else {
statusIdMax = statusList.get(holder.getBindingAdapterPosition() - 1).id;
@ -2263,13 +2214,24 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
boolean expand_media = sharedpreferences.getBoolean(context.getString(R.string.SET_EXPAND_MEDIA), false);
RequestBuilder<Drawable> requestBuilder;
GlideRequests glideRequests = GlideApp.with(context);
Bitmap placeholder = null;
if (attachment.blurhash != null) {
placeholder = new BlurHashDecoder().decode(attachment.blurhash, 32, 32, 1f);
}
if (!isSensitive || expand_media) {
requestBuilder = glideRequests.asDrawable();
if (!fullAttachement) {
if (placeholder != null) {
requestBuilder = requestBuilder.placeholder(new BitmapDrawable(context.getResources(), placeholder));
}
requestBuilder = requestBuilder.apply(new RequestOptions().transform(new GlideFocus(focusX, focusY)));
requestBuilder = requestBuilder.dontAnimate();
} else {
if (placeholder != null) {
requestBuilder = requestBuilder.placeholder(new BitmapDrawable(context.getResources(), placeholder));
} else {
requestBuilder = requestBuilder.placeholder(R.color.transparent_grey);
}
requestBuilder = requestBuilder.dontAnimate();
requestBuilder = requestBuilder.apply(new RequestOptions().override((int) mediaW, (int) mediaH));
requestBuilder = requestBuilder.fitCenter();
@ -2295,14 +2257,19 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
boolean expand_media = sharedpreferences.getBoolean(context.getString(R.string.SET_EXPAND_MEDIA), false);
LinearLayout.LayoutParams lp;
int defaultHeight = (int) Helper.convertDpToPixel(200, context);
if (measuredWidth > 0) {
defaultHeight = (int) (measuredWidth * 3) / 4;
}
if (fullAttachement && mediaH > 0 && (!statusToDeal.sensitive || expand_media)) {
lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) (mediaH * ratio));
layoutMediaBinding.media.setScaleType(ImageView.ScaleType.FIT_CENTER);
} else {
if (singleImage) {
lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) Helper.convertDpToPixel(200, context));
lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, defaultHeight);
} else {
lp = new LinearLayout.LayoutParams((int) Helper.convertDpToPixel(200, context), (int) Helper.convertDpToPixel(200, context));
//noinspection SuspiciousNameCombination
lp = new LinearLayout.LayoutParams(defaultHeight, defaultHeight);
}
layoutMediaBinding.media.setScaleType(ImageView.ScaleType.CENTER_CROP);
}
@ -2522,6 +2489,9 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
public List<Attachment> getPreloadItems(int position) {
List<Attachment> attachments = new ArrayList<>();
int max_size = statusList.size();
if (max_size == 0) {
return attachments;
}
int siblings = 3;
int from = Math.max((position - siblings), 0);
if (from > max_size - 1) {
@ -2698,7 +2668,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
status.isFetchMore = false;
notifyItemChanged(holder.getBindingAdapterPosition());
String fromId;
if (status.positionFetchMore == Status.PositionFetchMore.TOP) {
if (status.positionFetchMore == Status.PositionFetchMore.TOP || holder.getBindingAdapterPosition() == 0) {
fromId = statusList.get(holder.getBindingAdapterPosition()).id;
} else {
fromId = statusList.get(holder.getBindingAdapterPosition() - 1).id;
@ -2716,7 +2686,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
minId = status.id;
}
}
if (status.positionFetchMore == Status.PositionFetchMore.TOP) {
if (status.positionFetchMore == Status.PositionFetchMore.TOP || holder.getBindingAdapterPosition() == 0) {
maxId = statusList.get(holder.getBindingAdapterPosition()).id;
} else {
maxId = statusList.get(holder.getBindingAdapterPosition() - 1).id;
@ -2754,7 +2724,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
//We hide the button
status.isFetchMore = false;
String fromId;
if (status.positionFetchMore == Status.PositionFetchMore.TOP) {
if (status.positionFetchMore == Status.PositionFetchMore.TOP || holder.getBindingAdapterPosition() == 0) {
fromId = statusList.get(holder.getBindingAdapterPosition()).id;
} else {
fromId = statusList.get(holder.getBindingAdapterPosition() - 1).id;

View file

@ -132,6 +132,7 @@ public class FragmentMedia extends Fragment {
binding.pbarInf.setScaleY(1f);
binding.pbarInf.setIndeterminate(true);
binding.loader.setVisibility(View.VISIBLE);
scheduleStartPostponedTransition(binding.mediaPicture);
if (Helper.isValidContextForGlide(requireActivity()) && isAdded()) {
Glide.with(requireActivity())
.asBitmap()
@ -144,7 +145,7 @@ public class FragmentMedia extends Fragment {
return;
}
binding.mediaPicture.setImageBitmap(resource);
scheduleStartPostponedTransition(binding.mediaPicture);
if (attachment.type.equalsIgnoreCase("image") && !attachment.url.toLowerCase().endsWith(".gif")) {
binding.mediaPicture.setVisibility(View.VISIBLE);
final Handler handler = new Handler();

View file

@ -96,9 +96,11 @@ public class FragmentMediaProfile extends Fragment {
accountsVM.getAccountStatuses(tempInstance, null, accountId, null, null, null, null, null, true, false, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), statuses -> initializeStatusesCommonView(statuses));
} else {
if (isAdded() && !requireActivity().isFinishing()) {
Toasty.error(requireActivity(), getString(R.string.toast_fetch_error), Toasty.LENGTH_LONG).show();
}
}
}
});
} else {
tempToken = BaseMainActivity.currentToken;

View file

@ -30,7 +30,6 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import app.fedilab.android.R;
import app.fedilab.android.mastodon.client.endpoints.MastodonAnnouncementsService;
import app.fedilab.android.mastodon.client.endpoints.MastodonStatusesService;
import app.fedilab.android.mastodon.client.entities.api.Account;
import app.fedilab.android.mastodon.client.entities.api.Accounts;
@ -1293,48 +1292,4 @@ public class StatusesVM extends AndroidViewModel {
}).start();
return voidMutableLiveData;
}
/**
* React to a status with an emoji.
*
* @param instance Instance domain of the active account
* @param token Access token of the active account
* @param id Local ID of an announcement
* @param name Unicode emoji, or shortcode of custom emoji
*/
public void addReaction(@NonNull String instance, String token, @NonNull String id, @NonNull String name) {
MastodonStatusesService mastodonStatusesService = init(instance);
new Thread(() -> {
Call<Void> addReactionCall = mastodonStatusesService.addReaction(token, id, name);
if (addReactionCall != null) {
try {
addReactionCall.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
/**
* Undo a react emoji to a status.
*
* @param instance Instance domain of the active account
* @param token Access token of the active account
* @param id Local ID of an announcement
* @param name Unicode emoji, or shortcode of custom emoji
*/
public void removeReaction(@NonNull String instance, String token, @NonNull String id, @NonNull String name) {
MastodonStatusesService mastodonStatusesService = init(instance);
new Thread(() -> {
Call<Void> removeReactionCall = mastodonStatusesService.removeReaction(token, id, name);
if (removeReactionCall != null) {
try {
removeReactionCall.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}

View file

@ -39,12 +39,13 @@
<com.google.android.material.button.MaterialButton
android:id="@+id/remove"
style="@style/Widget.Material3.Button.OutlinedButton"
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_margin="6dp"
android:insetTop="0dp"
android:insetBottom="0dp"
android:contentDescription="@string/delete_field"
android:padding="0dp"
android:textColor="?colorError"
app:icon="@drawable/ic_compose_attachment_remove"

View file

@ -48,11 +48,18 @@
android:layout_marginHorizontal="6dp"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.Material3.TitleLarge"
app:layout_constraintBottom_toTopOf="@id/description"
app:layout_constraintBottom_toTopOf="@id/description_container"
app:layout_constraintTop_toTopOf="@id/background_image"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Instance" />
<androidx.core.widget.NestedScrollView
android:id="@+id/description_container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/version"
app:layout_constraintTop_toBottomOf="@id/name">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/description"
android:layout_width="match_parent"
@ -61,10 +68,10 @@
android:layout_marginTop="6dp"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.Material3.LabelMedium"
app:layout_constraintBottom_toTopOf="@id/version"
app:layout_constraintTop_toBottomOf="@id/name"
tools:maxLines="6"
tools:text="@tools:sample/lorem/random" />
</androidx.core.widget.NestedScrollView>
<com.google.android.material.textview.MaterialTextView
android:id="@+id/version"
@ -74,7 +81,7 @@
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.Material3.LabelMedium"
app:layout_constraintBottom_toTopOf="@id/uri"
app:layout_constraintTop_toBottomOf="@id/description"
app:layout_constraintTop_toBottomOf="@id/description_container"
tools:text="4.0" />
<com.google.android.material.button.MaterialButton
@ -106,7 +113,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="name,description,version,uri,contact"
app:constraint_referenced_ids="name,description_container,version,uri,contact"
tools:visibility="visible" />
<com.google.android.material.progressindicator.CircularProgressIndicator

View file

@ -57,6 +57,7 @@
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/status_boost_icon"
android:contentDescription="@string/reblog"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scaleType="centerInside"
@ -64,6 +65,7 @@
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/status_booster_avatar"
android:contentDescription="@string/profile_picture"
android:layout_width="20dp"
android:layout_height="20dp"
android:scaleType="centerInside"
@ -114,6 +116,7 @@
android:layout_width="36dp"
android:layout_height="36dp"
android:scaleType="centerInside"
android:contentDescription="@string/profile_picture"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -139,6 +142,7 @@
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="6dp"
android:contentDescription="@string/reply"
android:src="@drawable/ic_baseline_reply_16"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
@ -152,6 +156,7 @@
android:layout_marginStart="6dp"
android:src="@drawable/ic_baseline_android_24"
android:visibility="gone"
android:contentDescription="@string/bot"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:visibility="visible" />
@ -178,6 +183,7 @@
android:id="@+id/visibility_small"
android:layout_width="20dp"
android:layout_height="20dp"
android:contentDescription="@string/visibility"
android:layout_marginEnd="5dp"
android:src="@drawable/ic_baseline_public_24" />
@ -211,6 +217,7 @@
android:layout_height="20dp"
android:layout_gravity="center"
android:scaleType="centerInside"
android:contentDescription="@string/pinned"
android:src="@drawable/ic_baseline_push_pin_24"
android:visibility="gone" />
@ -357,6 +364,7 @@
android:layout_width="match_parent"
android:layout_height="150dp"
android:adjustViewBounds="true"
android:contentDescription="@string/card_picture"
android:padding="1dp"
android:scaleType="centerCrop"
android:visibility="gone"
@ -375,6 +383,7 @@
android:adjustViewBounds="true"
android:padding="1dp"
android:scaleType="centerCrop"
android:contentDescription="@string/card_picture"
android:visibility="gone"
tools:src="@tools:sample/backgrounds/scenic"
tools:visibility="visible" />
@ -531,6 +540,7 @@
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/repeat_info"
android:contentDescription="@string/reblog"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="12dp"
@ -554,6 +564,7 @@
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/fav_info"
android:layout_width="20dp"
android:contentDescription="@string/favourite"
android:layout_height="20dp"
android:layout_marginStart="12dp"
app:srcCompat="@drawable/ic_star_outline" />
@ -573,6 +584,7 @@
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/visibility"
android:contentDescription="@string/visibility"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="12dp"

View file

@ -335,6 +335,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/visibility_group"
android:padding="6dp"
app:singleSelection="true">

View file

@ -50,6 +50,7 @@
android:id="@+id/number_of_messages"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/number_of_replies"
android:layout_weight="2"
android:drawablePadding="5dp"
app:drawableStartCompat="@drawable/ic_baseline_message_24" />
@ -58,6 +59,7 @@
android:id="@+id/number_of_media"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/number_of_media"
android:layout_weight="2"
android:drawablePadding="5dp"
app:drawableStartCompat="@drawable/ic_baseline_perm_media_24" />
@ -66,6 +68,7 @@
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/update_date"
android:layout_weight="1"
android:drawablePadding="5dp"
app:drawableStartCompat="@drawable/ic_baseline_access_time_24" />

View file

@ -8,6 +8,7 @@
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/media"
android:adjustViewBounds="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"

View file

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>

View file

@ -1006,4 +1006,11 @@
<string name="set_fetch_home">Automaticky načítat domácí zprávy</string>
<string name="fetch_home_messages">Načíst domácí zprávy</string>
<string name="auto_fetch_missing">Automaticky načítat chybějící zprávy</string>
<string name="set_mention_at_top">Zmínky nahoře</string>
<string name="set_mention_at_top_indication">Při odpovídání budou zmínky vždy přidány na začátek zprávy</string>
<string name="pinned">Připnuto</string>
<string name="number_of_media">Počet médií</string>
<string name="number_of_replies">Počet odpovědí</string>
<string name="update_date">Datum aktualizace</string>
<string name="card_picture">Obrázek karty</string>
</resources>

View file

@ -996,4 +996,11 @@
<string name="otp_message">Zwei-Faktor-Authentifizierungstoken</string>
<string name="home_cache">Cache der Startseite</string>
<string name="fetch_home_messages">Beiträge auf der Startseite abrufen</string>
<string name="set_mention_at_top">Erwähnungen am Anfang</string>
<string name="set_mention_at_top_indication">Beim Antworten werden alle Erwähnungen dem Anfang des Beitrags hinzugefügt</string>
<string name="number_of_media">Medienanzahl</string>
<string name="number_of_replies">Anzahl von Antworten</string>
<string name="update_date">Datum der Aktualisierung</string>
<string name="pinned">Angeheftet</string>
<string name="card_picture">Bild der Karte</string>
</resources>

View file

@ -987,4 +987,6 @@
<string name="home_cache">Memòria temporànea lìnia printzipale</string>
<string name="type_of_home_delay_title">Tempus de recùperu de sa lìnia printzipale</string>
<string name="set_fetch_home">Recùpera in automàticu is messàgios de sa lìnia printzipale</string>
<string name="set_mention_at_top">Mentovos in pitzos</string>
<string name="set_mention_at_top_indication">Rispondende, is mentovos s\'ant a annànghere a su cumintzu de su messàgiu</string>
</resources>

View file

@ -994,4 +994,11 @@
<string name="home_cache">Ana sayfa önbelleği</string>
<string name="auto_fetch_missing">Eksik mesajları otomatik olarak al</string>
<string name="fetch_home_messages">Ana sayfa mesajlarını al</string>
<string name="set_mention_at_top">Bahsedilenler üstte</string>
<string name="set_mention_at_top_indication">Yanıtlarken, bahsedenlerin tümü mesajın başına eklenecektir</string>
<string name="card_picture">Kart resmi</string>
<string name="number_of_media">Medya sayısı</string>
<string name="number_of_replies">Yanıt sayısı</string>
<string name="pinned">Sabitlendi</string>
<string name="update_date">Güncelleme tarihi</string>
</resources>

View file

@ -942,7 +942,7 @@
<string name="type_of_notifications_delay_title">通知获取时间</string>
<string name="set_dynamic_color_indication">与您个人壁纸的配色方案色调一致。</string>
<string name="type_default_theme_light">默认浅色主题</string>
<string name="set_cardview">高架卡</string>
<string name="set_cardview">悬浮卡片</string>
<string name="set_customize_light">自定义浅色主题</string>
<string name="set_customize_light_indication">允许为浅色主题自定义消息中的一些元素。</string>
<string name="set_customize_dark">自定义深色主题</string>
@ -994,4 +994,11 @@
<string name="type_of_home_delay_title">主页获取延迟</string>
<string name="fetch_home_every">获取主页消息每隔</string>
<string name="auto_fetch_missing">自动获取缺失的消息</string>
<string name="set_mention_at_top">置顶提及</string>
<string name="set_mention_at_top_indication">回复时提及将全部添加到消息的开头</string>
<string name="pinned">已置顶</string>
<string name="card_picture">卡片图像</string>
<string name="number_of_replies">回复数</string>
<string name="update_date">更新日期</string>
<string name="number_of_media">媒体数</string>
</resources>

View file

@ -2044,6 +2044,8 @@
<string name="action_unpin">Unpin message</string>
<string name="toast_unpin">The message is no longer pinned!</string>
<string name="toast_pin">The message has been pinned</string>
<string name="pinned">Pinned</string>
<string name="card_picture">Card picture</string>
<string name="set_live_translate_title">Translate messages</string>
<string name="set_live_translate">Force translation to a specific language. Choose first value to reset to device settings</string>
<string name="edit_message">Edit message</string>
@ -2249,4 +2251,9 @@
<string name="set_mention_at_top">Mentions at the top</string>
<string name="set_mention_at_top_indication">When replying mentions will all be added to the beginning of the message</string>
<string name="number_of_media">Number of media</string>
<string name="number_of_replies">Number of replies</string>
<string name="update_date">Update date</string>
</resources>