added image description, version upgrade, removed social media icons

This commit is contained in:
nuclearfog 2023-04-30 19:17:26 +02:00
parent 088843d140
commit 1171a5ce7d
No known key found for this signature in database
GPG Key ID: 03488A185C476379
17 changed files with 235 additions and 78 deletions

View File

@ -11,8 +11,8 @@ android {
applicationId 'org.nuclearfog.twidda' applicationId 'org.nuclearfog.twidda'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 33 targetSdkVersion 33
versionCode 83 versionCode 84
versionName '3.1.3' versionName '3.1.4'
resConfigs 'en', 'de-rDE', 'zh-rCN' resConfigs 'en', 'de-rDE', 'zh-rCN'
} }

View File

@ -33,10 +33,16 @@ public class MastodonMedia implements Media {
*/ */
private static final String TYPE_VIDEO = "video"; private static final String TYPE_VIDEO = "video";
/**
* Mastodon audio type
*/
private static final String TYPE_AUDIO = "audio";
private String key; private String key;
private String url; private String url;
private String preview = ""; private String preview = "";
private int type = NONE; private String description = "";
private int type = UNDEFINED;
/** /**
* @param json Mastodon status JSON format * @param json Mastodon status JSON format
@ -59,6 +65,10 @@ public class MastodonMedia implements Media {
case TYPE_VIDEO: case TYPE_VIDEO:
type = VIDEO; type = VIDEO;
break; break;
case TYPE_AUDIO:
type = AUDIO;
break;
} }
if (Patterns.WEB_URL.matcher(url).matches()) { if (Patterns.WEB_URL.matcher(url).matches()) {
this.url = url; this.url = url;
@ -68,6 +78,9 @@ public class MastodonMedia implements Media {
if (Patterns.WEB_URL.matcher(preview).matches()) { if (Patterns.WEB_URL.matcher(preview).matches()) {
this.preview = preview; this.preview = preview;
} }
if (json.has("description") && !json.isNull("description")) {
description = json.getString("description");
}
} }
@ -95,6 +108,12 @@ public class MastodonMedia implements Media {
} }
@Override
public String getDescription() {
return description;
}
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable Object obj) {
return obj instanceof Media && ((Media) obj).getKey().equals(getKey()); return obj instanceof Media && ((Media) obj).getKey().equals(getKey());
@ -104,24 +123,24 @@ public class MastodonMedia implements Media {
@NonNull @NonNull
@Override @Override
public String toString() { public String toString() {
String tostring; String tostring = "type=";
switch (getMediaType()) { switch (getMediaType()) {
case PHOTO: case PHOTO:
tostring = "photo:"; tostring += "photo";
break; break;
case VIDEO: case VIDEO:
tostring = "video:"; tostring += "video";
break; break;
case GIF: case GIF:
tostring = "gif:"; tostring += "gif";
break; break;
default: default:
tostring = "none:"; tostring += "none";
break; break;
} }
return tostring + "url=\"" + getUrl() + "\""; return tostring + " url=\"" + getUrl() + "\"";
} }
} }

View File

@ -39,7 +39,7 @@ public class MediaV1 implements Media {
*/ */
private static final String TYPE_VIDEO = "video"; private static final String TYPE_VIDEO = "video";
private int type = NONE; private int type = UNDEFINED;
private String url = ""; private String url = "";
private String previewUrl = ""; private String previewUrl = "";
private String key; private String key;
@ -127,6 +127,12 @@ public class MediaV1 implements Media {
} }
@Override
public String getDescription() {
return "";
}
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable Object obj) {
return obj instanceof Media && ((Media) obj).getKey().equals(getKey()); return obj instanceof Media && ((Media) obj).getKey().equals(getKey());
@ -136,24 +142,24 @@ public class MediaV1 implements Media {
@NonNull @NonNull
@Override @Override
public String toString() { public String toString() {
String tostring; String tostring = "type=";
switch (getMediaType()) { switch (getMediaType()) {
case PHOTO: case PHOTO:
tostring = "photo:"; tostring += "photo";
break; break;
case VIDEO: case VIDEO:
tostring = "video:"; tostring += "video";
break; break;
case GIF: case GIF:
tostring = "gif:"; tostring += "gif";
break; break;
default: default:
tostring = "none:"; tostring += "none";
break; break;
} }
return tostring + "url=\"" + getUrl() + "\""; return tostring + " url=\"" + getUrl() + "\"";
} }
} }

View File

@ -47,7 +47,7 @@ public class MediaV2 implements Media {
private String key; private String key;
private String preview; private String preview;
private String url = ""; private String url = "";
private int type = NONE; private int type = UNDEFINED;
/** /**
* @param mediaItem Twitter media json format * @param mediaItem Twitter media json format
@ -133,6 +133,12 @@ public class MediaV2 implements Media {
} }
@Override
public String getDescription() {
return "";
}
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable Object obj) {
return obj instanceof Media && ((Media) obj).getKey().equals(getKey()); return obj instanceof Media && ((Media) obj).getKey().equals(getKey());
@ -142,24 +148,24 @@ public class MediaV2 implements Media {
@NonNull @NonNull
@Override @Override
public String toString() { public String toString() {
String tostring; String tostring = "type=";
switch (getMediaType()) { switch (getMediaType()) {
case PHOTO: case PHOTO:
tostring = "photo:"; tostring += "photo";
break; break;
case VIDEO: case VIDEO:
tostring = "video:"; tostring += "video";
break; break;
case GIF: case GIF:
tostring = "gif:"; tostring += "gif";
break; break;
default: default:
tostring = "none:"; tostring += "none";
break; break;
} }
return tostring + "url=\"" + getUrl() + "\""; return tostring + " url=\"" + getUrl() + "\"";
} }
} }

View File

@ -7,7 +7,6 @@ import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Point;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
@ -251,10 +250,9 @@ public class AppStyles {
} }
image = crop.transform(image); image = crop.transform(image);
} }
Point displaySize = new Point(); int widthPixels = Resources.getSystem().getDisplayMetrics().widthPixels;
activity.getWindowManager().getDefaultDisplay().getSize(displaySize); int blurRadius = Math.max(Math.round(widthPixels * 10.0f / image.getWidth()), 10);
int blurRadius = Math.max(Math.round(displaySize.x * 10.0f / image.getWidth()), 10); float toolbarRatio = activity.getResources().getDimension(R.dimen.profile_toolbar_height) / widthPixels;
float toolbarRatio = activity.getResources().getDimension(R.dimen.profile_toolbar_height) / displaySize.x;
// do final transformations (crop first image to toolbar background size, then blur) // do final transformations (crop first image to toolbar background size, then blur)
BlurTransformation blur = new BlurTransformation(activity.getApplicationContext(), blurRadius); BlurTransformation blur = new BlurTransformation(activity.getApplicationContext(), blurRadius);
CropTransformation crop = new CropTransformation(image.getWidth(), (int) (image.getWidth() * toolbarRatio), GravityHorizontal.CENTER, GravityVertical.TOP); CropTransformation crop = new CropTransformation(image.getWidth(), (int) (image.getWidth() * toolbarRatio), GravityHorizontal.CENTER, GravityVertical.TOP);

View File

@ -20,7 +20,7 @@ public class DatabaseAdapter {
/** /**
* database version * database version
*/ */
private static final int DB_VERSION = 17; private static final int DB_VERSION = 18;
/** /**
* database file name * database file name
@ -129,6 +129,7 @@ public class DatabaseAdapter {
+ MediaTable.KEY + " TEXT PRIMARY KEY," + MediaTable.KEY + " TEXT PRIMARY KEY,"
+ MediaTable.TYPE + " INTEGER," + MediaTable.TYPE + " INTEGER,"
+ MediaTable.URL + " TEXT," + MediaTable.URL + " TEXT,"
+ MediaTable.DESCRIPTION + " TEXT,"
+ MediaTable.PREVIEW + " TEXT);"; + MediaTable.PREVIEW + " TEXT);";
/** /**
@ -314,6 +315,11 @@ public class DatabaseAdapter {
*/ */
private static final String UPDATE_STATUS_ADD_MENTIONS = "ALTER TABLE " + StatusTable.NAME + " ADD " + StatusTable.MENTIONS + " TEXT;"; private static final String UPDATE_STATUS_ADD_MENTIONS = "ALTER TABLE " + StatusTable.NAME + " ADD " + StatusTable.MENTIONS + " TEXT;";
/**
* add mediatable description
*/
private static final String UPDATE_MEDIA_ADD_DESCRIPTION = "ALTER TABLE " + MediaTable.NAME + " ADD " + MediaTable.DESCRIPTION + " TEXT;";
/** /**
* singleton instance * singleton instance
*/ */
@ -360,7 +366,9 @@ public class DatabaseAdapter {
// set initial version // set initial version
if (db.getVersion() == 0) { if (db.getVersion() == 0) {
db.setVersion(DB_VERSION); db.setVersion(DB_VERSION);
} else { }
// update table
else if (db.getVersion() != DB_VERSION) {
if (db.getVersion() < 6) { if (db.getVersion() < 6) {
db.execSQL(UPDATE_ACCOUNT_ADD_HOST); db.execSQL(UPDATE_ACCOUNT_ADD_HOST);
db.execSQL(UPDATE_ACCOUNT_ADD_CLIENT_ID); db.execSQL(UPDATE_ACCOUNT_ADD_CLIENT_ID);
@ -403,8 +411,12 @@ public class DatabaseAdapter {
db.execSQL(UPDATE_USER_ADD_EMOJI); db.execSQL(UPDATE_USER_ADD_EMOJI);
db.setVersion(16); db.setVersion(16);
} }
if (db.getVersion() < DB_VERSION) { if (db.getVersion() < 17) {
db.execSQL(UPDATE_STATUS_ADD_MENTIONS); db.execSQL(UPDATE_STATUS_ADD_MENTIONS);
db.setVersion(17);
}
if (db.getVersion() < DB_VERSION) {
db.execSQL(UPDATE_MEDIA_ADD_DESCRIPTION);
db.setVersion(DB_VERSION); db.setVersion(DB_VERSION);
} }
} }
@ -964,6 +976,11 @@ public class DatabaseAdapter {
* url for the media thumbnail * url for the media thumbnail
*/ */
String PREVIEW = "media_preview_url"; String PREVIEW = "media_preview_url";
/**
* description of the media
*/
String DESCRIPTION = "media_description";
} }
/** /**

View File

@ -20,12 +20,13 @@ public class DatabaseMedia implements Media, MediaTable {
/** /**
* *
*/ */
public static final String[] PROJECTION = {KEY, URL, PREVIEW, TYPE}; public static final String[] PROJECTION = {KEY, URL, PREVIEW, TYPE, DESCRIPTION};
private int mediaType; private int mediaType;
private String key = ""; private String key = "";
private String url = ""; private String url = "";
private String preview = ""; private String preview = "";
private String description = "";
/** /**
@ -35,6 +36,7 @@ public class DatabaseMedia implements Media, MediaTable {
String key = cursor.getString(0); String key = cursor.getString(0);
String url = cursor.getString(1); String url = cursor.getString(1);
String preview = cursor.getString(2); String preview = cursor.getString(2);
String description = cursor.getString(3);
mediaType = cursor.getInt(3); mediaType = cursor.getInt(3);
if (key != null) if (key != null)
this.key = key; this.key = key;
@ -42,6 +44,8 @@ public class DatabaseMedia implements Media, MediaTable {
this.url = url; this.url = url;
if (preview != null) if (preview != null)
this.preview = preview; this.preview = preview;
if (description != null)
this.description = description;
} }
@ -69,6 +73,12 @@ public class DatabaseMedia implements Media, MediaTable {
} }
@Override
public String getDescription() {
return description;
}
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable Object obj) {
return obj instanceof Media && ((Media) obj).getKey().equals(getKey()); return obj instanceof Media && ((Media) obj).getKey().equals(getKey());
@ -78,24 +88,24 @@ public class DatabaseMedia implements Media, MediaTable {
@NonNull @NonNull
@Override @Override
public String toString() { public String toString() {
String tostring; String tostring = "type=";
switch (getMediaType()) { switch (getMediaType()) {
case PHOTO: case PHOTO:
tostring = "photo:"; tostring += "photo";
break; break;
case VIDEO: case VIDEO:
tostring = "video:"; tostring += "video";
break; break;
case GIF: case GIF:
tostring = "gif:"; tostring += "gif";
break; break;
default: default:
tostring = "none:"; tostring += "none";
break; break;
} }
return tostring + "url=\"" + getUrl() + "\""; return tostring + " url=\"" + getUrl() + "\"";
} }
} }

View File

@ -10,32 +10,37 @@ import java.io.Serializable;
public interface Media extends Serializable, Comparable<Media> { public interface Media extends Serializable, Comparable<Media> {
/** /**
* returned when the status doesn't contain any media * media is undefined
*/ */
int NONE = -1; int UNDEFINED = -1;
/** /**
* returned when the status contains one or more images * media is a image
*/ */
int PHOTO = 800; int PHOTO = 800;
/** /**
* returned when the status contains a video * media is a video
*/ */
int VIDEO = 801; int VIDEO = 801;
/** /**
* returned when the status contains an animated gif * media is an animated gif
*/ */
int GIF = 802; int GIF = 802;
/**
* media is an audio
*/
int AUDIO = 803;
/** /**
* @return media key * @return media key
*/ */
String getKey(); String getKey();
/** /**
* @return type of media e.g. video or image {@link #NONE,#GIF,#PHOTO,#VIDEO} * @return type of media e.g. video or image {@link #UNDEFINED ,#GIF,#PHOTO,#VIDEO}
*/ */
int getMediaType(); int getMediaType();
@ -49,6 +54,11 @@ public interface Media extends Serializable, Comparable<Media> {
*/ */
String getPreviewUrl(); String getPreviewUrl();
/**
* @return additional media description
*/
String getDescription();
@Override @Override
default int compareTo(Media o) { default int compareTo(Media o) {

View File

@ -22,6 +22,7 @@ import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler; import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.ui.views.AnimatedImageView; import org.nuclearfog.twidda.ui.views.AnimatedImageView;
import org.nuclearfog.twidda.ui.views.DescriptionView;
import org.nuclearfog.zoomview.ZoomView; import org.nuclearfog.zoomview.ZoomView;
import java.io.File; import java.io.File;
@ -56,6 +57,12 @@ public class ImageViewer extends MediaActivity implements AsyncCallback<ImageRes
*/ */
public static final String IMAGE_TYPE = "image-type"; public static final String IMAGE_TYPE = "image-type";
/**
* key to set image description
* value type is String
*/
public static final String IMAGE_DESCRIPTION = "image-description";
/** /**
* name of the cache folder where online images will be stored * name of the cache folder where online images will be stored
* after the end of this activity this folder will be cleared * after the end of this activity this folder will be cleared
@ -81,6 +88,7 @@ public class ImageViewer extends MediaActivity implements AsyncCallback<ImageRes
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.page_image); setContentView(R.layout.page_image);
Toolbar toolbar = findViewById(R.id.page_image_toolbar); Toolbar toolbar = findViewById(R.id.page_image_toolbar);
DescriptionView descriptionView = findViewById(R.id.page_image_description);
loadingCircle = findViewById(R.id.page_image_progress); loadingCircle = findViewById(R.id.page_image_progress);
zoomImage = findViewById(R.id.page_image_viewer); zoomImage = findViewById(R.id.page_image_viewer);
gifImage = findViewById(R.id.page_image_gif); gifImage = findViewById(R.id.page_image_gif);
@ -96,6 +104,7 @@ public class ImageViewer extends MediaActivity implements AsyncCallback<ImageRes
Uri data = getIntent().getParcelableExtra(IMAGE_URI); Uri data = getIntent().getParcelableExtra(IMAGE_URI);
mode = getIntent().getIntExtra(IMAGE_TYPE, IMAGE_DEFAULT); mode = getIntent().getIntExtra(IMAGE_TYPE, IMAGE_DEFAULT);
String description = getIntent().getStringExtra(IMAGE_DESCRIPTION);
boolean isLocalFile = !data.getScheme().startsWith("http"); boolean isLocalFile = !data.getScheme().startsWith("http");
switch (mode) { switch (mode) {
@ -124,6 +133,11 @@ public class ImageViewer extends MediaActivity implements AsyncCallback<ImageRes
loadingCircle.setVisibility(View.INVISIBLE); loadingCircle.setVisibility(View.INVISIBLE);
toolbar.setVisibility(View.GONE); toolbar.setVisibility(View.GONE);
} }
if (description != null && !description.trim().isEmpty()) {
descriptionView.setDescription(description);
} else {
descriptionView.setVisibility(View.INVISIBLE);
}
} }

View File

@ -6,7 +6,7 @@ import static org.nuclearfog.twidda.ui.activities.ProfileActivity.TOOLBAR_TRANSP
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Point; import android.content.res.Resources;
import android.location.Location; import android.location.Location;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@ -213,9 +213,8 @@ public class ProfileEditor extends MediaActivity implements OnClickListener, Asy
// Add image as banner image // Add image as banner image
else if (resultType == REQUEST_BANNER) { else if (resultType == REQUEST_BANNER) {
if (holder.setBanner(this, uri)) { if (holder.setBanner(this, uri)) {
Point displaySize = new Point(); int widthPixels = Resources.getSystem().getDisplayMetrics().widthPixels;
getWindowManager().getDefaultDisplay().getSize(displaySize); picasso.load(uri).resize(widthPixels, widthPixels / 3).centerCrop(Gravity.TOP).into(profile_banner, this);
picasso.load(uri).resize(displaySize.x, displaySize.x / 3).centerCrop(Gravity.TOP).into(profile_banner, this);
addBannerBtn.setVisibility(INVISIBLE); addBannerBtn.setVisibility(INVISIBLE);
changeBannerBtn.setVisibility(VISIBLE); changeBannerBtn.setVisibility(VISIBLE);
} else { } else {

View File

@ -765,6 +765,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
if (media.getMediaType() == Media.PHOTO) { if (media.getMediaType() == Media.PHOTO) {
Intent intent = new Intent(this, ImageViewer.class); Intent intent = new Intent(this, ImageViewer.class);
intent.putExtra(ImageViewer.IMAGE_URI, uri); intent.putExtra(ImageViewer.IMAGE_URI, uri);
intent.putExtra(ImageViewer.IMAGE_DESCRIPTION, media.getDescription());
intent.putExtra(ImageViewer.IMAGE_TYPE, ImageViewer.IMAGE_DEFAULT); intent.putExtra(ImageViewer.IMAGE_TYPE, ImageViewer.IMAGE_DEFAULT);
startActivity(intent); startActivity(intent);
} else if (media.getMediaType() == Media.VIDEO) { } else if (media.getMediaType() == Media.VIDEO) {

View File

@ -28,11 +28,6 @@ public class NetworkAdapter extends BaseAdapter {
*/ */
public static final int ID_MASTODON = 20; public static final int ID_MASTODON = 20;
/**
* social network icons
*/
private static final int[] ICONS = {R.drawable.mastodon, R.drawable.twitter};
/** /**
* social network names * social network names
*/ */
@ -55,7 +50,7 @@ public class NetworkAdapter extends BaseAdapter {
@Override @Override
public int getCount() { public int getCount() {
return ICONS.length; return IDS.length;
} }
@ -80,7 +75,6 @@ public class NetworkAdapter extends BaseAdapter {
} }
textItem = convertView.findViewById(R.id.dropdown_textitem); textItem = convertView.findViewById(R.id.dropdown_textitem);
textItem.setText(STRINGS[position]); textItem.setText(STRINGS[position]);
textItem.setCompoundDrawablesWithIntrinsicBounds(ICONS[position], 0, 0, 0);
textItem.setTextColor(settings.getTextColor()); textItem.setTextColor(settings.getTextColor());
textItem.setBackgroundColor(settings.getCardColor()); textItem.setBackgroundColor(settings.getCardColor());
AppStyles.setDrawableColor(textItem, settings.getIconColor()); AppStyles.setDrawableColor(textItem, settings.getIconColor());

View File

@ -0,0 +1,91 @@
package org.nuclearfog.twidda.ui.views;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.config.GlobalSettings;
/**
* Description label view used to show image description
*
* @author nuclearfog
*/
public class DescriptionView extends LinearLayout implements OnClickListener {
/**
* background transparency color mask
*/
private static final int TRANSPARENCY_MASK = 0x7FFFFFFF;
private ImageView closeButton;
private TextView label;
/**
* @inheritDoc
*/
public DescriptionView(Context context) {
this(context, null);
}
/**
* @inheritDoc
*/
public DescriptionView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
GlobalSettings settings = GlobalSettings.getInstance(context);
int padding = (int) getResources().getDimension(R.dimen.descriptionview_layout_padding);
int displayWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
closeButton = new ImageView(context);
label = new TextView(context);
Drawable background = ResourcesCompat.getDrawable(getResources(), R.drawable.background, null);
Drawable closeIcon = ResourcesCompat.getDrawable(getResources(), R.drawable.cross, null);
if (background != null)
background.setColorFilter(settings.getBackgroundColor() & TRANSPARENCY_MASK, PorterDuff.Mode.SRC_IN);
if (closeIcon != null)
closeIcon.setColorFilter(settings.getIconColor(), PorterDuff.Mode.SRC_IN);
label.setPadding(padding, 0, 0, 0);
label.setMaxLines(4);
label.setMaxWidth(displayWidth / 2);
label.setTextColor(settings.getTextColor());
closeButton.setImageDrawable(closeIcon);
setBackground(background);
setPadding(padding, padding, padding, padding);
setOrientation(HORIZONTAL);
addView(closeButton);
addView(label);
closeButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == closeButton) {
setVisibility(INVISIBLE);
}
}
/**
* set description
*
* @param description description text
*/
public void setDescription(String description) {
label.setText(description);
}
}

View File

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="216.41"
android:viewportHeight="232.01">
<path
android:pathData="M211.81,139.09c-3.18,16.37 -28.49,34.28 -57.56,37.75 -15.16,1.81 -30.08,3.47 -46,2.74 -26.03,-1.19 -46.56,-6.21 -46.56,-6.21 0,2.53 0.16,4.95 0.47,7.2 3.38,25.69 25.47,27.23 46.39,27.94 21.12,0.72 39.92,-5.21 39.92,-5.21l0.87,19.09s-14.77,7.93 -41.08,9.39c-14.51,0.8 -32.52,-0.37 -53.51,-5.92C9.23,213.82 1.41,165.31 0.21,116.09c-0.37,-14.61 -0.14,-28.39 -0.14,-39.92 0,-50.33 32.98,-65.08 32.98,-65.08C49.67,3.45 78.2,0.24 107.86,0h0.73c29.66,0.24 58.21,3.45 74.84,11.09 0,0 32.97,14.75 32.97,65.08 0,0 0.41,37.13 -4.6,62.92"
android:fillColor="#ffffffff" />
<path
android:pathData="M177.51,80.08v60.94h-24.14v-59.15c0,-12.47 -5.25,-18.8 -15.74,-18.8 -11.6,0 -17.42,7.51 -17.42,22.35v32.38H96.21V85.42c0,-14.85 -5.82,-22.35 -17.42,-22.35 -10.49,0 -15.74,6.33 -15.74,18.8v59.15H38.9V80.08c0,-12.45 3.17,-22.35 9.54,-29.67 6.57,-7.32 15.17,-11.08 25.85,-11.08 12.35,0 21.71,4.75 27.9,14.25l6.01,10.08 6.01,-10.08c6.18,-9.5 15.54,-14.25 27.9,-14.25 10.68,0 19.28,3.75 25.85,11.08 6.37,7.32 9.54,17.22 9.54,29.67"
android:fillColor="#5a5a5a5a" />
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M17.316,6.246c0.008,0.162 0.011,0.326 0.011,0.488c0,4.99 -3.797,10.742 -10.74,10.742c-2.133,0 -4.116,-0.625 -5.787,-1.697c0.296,0.035 0.596,0.053 0.9,0.053c1.77,0 3.397,-0.604 4.688,-1.615c-1.651,-0.031 -3.046,-1.121 -3.526,-2.621c0.23,0.043 0.467,0.066 0.71,0.066c0.345,0 0.679,-0.045 0.995,-0.131C2.84,11.183 1.539,9.658 1.539,7.828c0,-0.016 0,-0.031 0,-0.047c0.509,0.283 1.092,0.453 1.71,0.473c-1.013,-0.678 -1.68,-1.832 -1.68,-3.143c0,-0.691 0.186,-1.34 0.512,-1.898C3.942,5.498 6.725,7 9.862,7.158C9.798,6.881 9.765,6.594 9.765,6.297c0,-2.084 1.689,-3.773 3.774,-3.773c1.086,0 2.067,0.457 2.756,1.191c0.859,-0.17 1.667,-0.484 2.397,-0.916c-0.282,0.881 -0.881,1.621 -1.66,2.088c0.764,-0.092 1.49,-0.293 2.168,-0.594C18.694,5.051 18.054,5.715 17.316,6.246z"
android:fillColor="#FFFFFF" />
</vector>

View File

@ -31,8 +31,8 @@
<org.nuclearfog.twidda.ui.views.AnimatedImageView <org.nuclearfog.twidda.ui.views.AnimatedImageView
android:id="@+id/page_image_gif" android:id="@+id/page_image_gif"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/page_image_toolbar" app:layout_constraintTop_toBottomOf="@id/page_image_toolbar"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@ -48,4 +48,15 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />
<org.nuclearfog.twidda.ui.views.DescriptionView
android:id="@+id/page_image_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/page_image_toolbar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintVertical_bias="0.9" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -302,4 +302,6 @@
<dimen name="item_emoji_text_size">18sp</dimen> <dimen name="item_emoji_text_size">18sp</dimen>
<dimen name="item_emoji_text_margin">8dp</dimen> <dimen name="item_emoji_text_margin">8dp</dimen>
<!--dimens of DescriptionView-->
<dimen name="descriptionview_layout_padding">5dp</dimen>
</resources> </resources>