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'
minSdkVersion 21
targetSdkVersion 33
versionCode 83
versionName '3.1.3'
versionCode 84
versionName '3.1.4'
resConfigs 'en', 'de-rDE', 'zh-rCN'
}

View File

@ -33,10 +33,16 @@ public class MastodonMedia implements Media {
*/
private static final String TYPE_VIDEO = "video";
/**
* Mastodon audio type
*/
private static final String TYPE_AUDIO = "audio";
private String key;
private String url;
private String preview = "";
private int type = NONE;
private String description = "";
private int type = UNDEFINED;
/**
* @param json Mastodon status JSON format
@ -59,6 +65,10 @@ public class MastodonMedia implements Media {
case TYPE_VIDEO:
type = VIDEO;
break;
case TYPE_AUDIO:
type = AUDIO;
break;
}
if (Patterns.WEB_URL.matcher(url).matches()) {
this.url = url;
@ -68,6 +78,9 @@ public class MastodonMedia implements Media {
if (Patterns.WEB_URL.matcher(preview).matches()) {
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
public boolean equals(@Nullable Object obj) {
return obj instanceof Media && ((Media) obj).getKey().equals(getKey());
@ -104,24 +123,24 @@ public class MastodonMedia implements Media {
@NonNull
@Override
public String toString() {
String tostring;
String tostring = "type=";
switch (getMediaType()) {
case PHOTO:
tostring = "photo:";
tostring += "photo";
break;
case VIDEO:
tostring = "video:";
tostring += "video";
break;
case GIF:
tostring = "gif:";
tostring += "gif";
break;
default:
tostring = "none:";
tostring += "none";
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 int type = NONE;
private int type = UNDEFINED;
private String url = "";
private String previewUrl = "";
private String key;
@ -127,6 +127,12 @@ public class MediaV1 implements Media {
}
@Override
public String getDescription() {
return "";
}
@Override
public boolean equals(@Nullable Object obj) {
return obj instanceof Media && ((Media) obj).getKey().equals(getKey());
@ -136,24 +142,24 @@ public class MediaV1 implements Media {
@NonNull
@Override
public String toString() {
String tostring;
String tostring = "type=";
switch (getMediaType()) {
case PHOTO:
tostring = "photo:";
tostring += "photo";
break;
case VIDEO:
tostring = "video:";
tostring += "video";
break;
case GIF:
tostring = "gif:";
tostring += "gif";
break;
default:
tostring = "none:";
tostring += "none";
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 preview;
private String url = "";
private int type = NONE;
private int type = UNDEFINED;
/**
* @param mediaItem Twitter media json format
@ -133,6 +133,12 @@ public class MediaV2 implements Media {
}
@Override
public String getDescription() {
return "";
}
@Override
public boolean equals(@Nullable Object obj) {
return obj instanceof Media && ((Media) obj).getKey().equals(getKey());
@ -142,24 +148,24 @@ public class MediaV2 implements Media {
@NonNull
@Override
public String toString() {
String tostring;
String tostring = "type=";
switch (getMediaType()) {
case PHOTO:
tostring = "photo:";
tostring += "photo";
break;
case VIDEO:
tostring = "video:";
tostring += "video";
break;
case GIF:
tostring = "gif:";
tostring += "gif";
break;
default:
tostring = "none:";
tostring += "none";
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.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.BitmapDrawable;
@ -251,10 +250,9 @@ public class AppStyles {
}
image = crop.transform(image);
}
Point displaySize = new Point();
activity.getWindowManager().getDefaultDisplay().getSize(displaySize);
int blurRadius = Math.max(Math.round(displaySize.x * 10.0f / image.getWidth()), 10);
float toolbarRatio = activity.getResources().getDimension(R.dimen.profile_toolbar_height) / displaySize.x;
int widthPixels = Resources.getSystem().getDisplayMetrics().widthPixels;
int blurRadius = Math.max(Math.round(widthPixels * 10.0f / image.getWidth()), 10);
float toolbarRatio = activity.getResources().getDimension(R.dimen.profile_toolbar_height) / widthPixels;
// do final transformations (crop first image to toolbar background size, then blur)
BlurTransformation blur = new BlurTransformation(activity.getApplicationContext(), blurRadius);
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
*/
private static final int DB_VERSION = 17;
private static final int DB_VERSION = 18;
/**
* database file name
@ -129,6 +129,7 @@ public class DatabaseAdapter {
+ MediaTable.KEY + " TEXT PRIMARY KEY,"
+ MediaTable.TYPE + " INTEGER,"
+ MediaTable.URL + " TEXT,"
+ MediaTable.DESCRIPTION + " 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;";
/**
* add mediatable description
*/
private static final String UPDATE_MEDIA_ADD_DESCRIPTION = "ALTER TABLE " + MediaTable.NAME + " ADD " + MediaTable.DESCRIPTION + " TEXT;";
/**
* singleton instance
*/
@ -360,7 +366,9 @@ public class DatabaseAdapter {
// set initial version
if (db.getVersion() == 0) {
db.setVersion(DB_VERSION);
} else {
}
// update table
else if (db.getVersion() != DB_VERSION) {
if (db.getVersion() < 6) {
db.execSQL(UPDATE_ACCOUNT_ADD_HOST);
db.execSQL(UPDATE_ACCOUNT_ADD_CLIENT_ID);
@ -403,8 +411,12 @@ public class DatabaseAdapter {
db.execSQL(UPDATE_USER_ADD_EMOJI);
db.setVersion(16);
}
if (db.getVersion() < DB_VERSION) {
if (db.getVersion() < 17) {
db.execSQL(UPDATE_STATUS_ADD_MENTIONS);
db.setVersion(17);
}
if (db.getVersion() < DB_VERSION) {
db.execSQL(UPDATE_MEDIA_ADD_DESCRIPTION);
db.setVersion(DB_VERSION);
}
}
@ -964,6 +976,11 @@ public class DatabaseAdapter {
* url for the media thumbnail
*/
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 String key = "";
private String url = "";
private String preview = "";
private String description = "";
/**
@ -35,6 +36,7 @@ public class DatabaseMedia implements Media, MediaTable {
String key = cursor.getString(0);
String url = cursor.getString(1);
String preview = cursor.getString(2);
String description = cursor.getString(3);
mediaType = cursor.getInt(3);
if (key != null)
this.key = key;
@ -42,6 +44,8 @@ public class DatabaseMedia implements Media, MediaTable {
this.url = url;
if (preview != null)
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
public boolean equals(@Nullable Object obj) {
return obj instanceof Media && ((Media) obj).getKey().equals(getKey());
@ -78,24 +88,24 @@ public class DatabaseMedia implements Media, MediaTable {
@NonNull
@Override
public String toString() {
String tostring;
String tostring = "type=";
switch (getMediaType()) {
case PHOTO:
tostring = "photo:";
tostring += "photo";
break;
case VIDEO:
tostring = "video:";
tostring += "video";
break;
case GIF:
tostring = "gif:";
tostring += "gif";
break;
default:
tostring = "none:";
tostring += "none";
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> {
/**
* 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;
/**
* returned when the status contains a video
* media is a video
*/
int VIDEO = 801;
/**
* returned when the status contains an animated gif
* media is an animated gif
*/
int GIF = 802;
/**
* media is an audio
*/
int AUDIO = 803;
/**
* @return media key
*/
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();
@ -49,6 +54,11 @@ public interface Media extends Serializable, Comparable<Media> {
*/
String getPreviewUrl();
/**
* @return additional media description
*/
String getDescription();
@Override
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.config.GlobalSettings;
import org.nuclearfog.twidda.ui.views.AnimatedImageView;
import org.nuclearfog.twidda.ui.views.DescriptionView;
import org.nuclearfog.zoomview.ZoomView;
import java.io.File;
@ -56,6 +57,12 @@ public class ImageViewer extends MediaActivity implements AsyncCallback<ImageRes
*/
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
* 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);
setContentView(R.layout.page_image);
Toolbar toolbar = findViewById(R.id.page_image_toolbar);
DescriptionView descriptionView = findViewById(R.id.page_image_description);
loadingCircle = findViewById(R.id.page_image_progress);
zoomImage = findViewById(R.id.page_image_viewer);
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);
mode = getIntent().getIntExtra(IMAGE_TYPE, IMAGE_DEFAULT);
String description = getIntent().getStringExtra(IMAGE_DESCRIPTION);
boolean isLocalFile = !data.getScheme().startsWith("http");
switch (mode) {
@ -124,6 +133,11 @@ public class ImageViewer extends MediaActivity implements AsyncCallback<ImageRes
loadingCircle.setVisibility(View.INVISIBLE);
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.Intent;
import android.graphics.Point;
import android.content.res.Resources;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
@ -213,9 +213,8 @@ public class ProfileEditor extends MediaActivity implements OnClickListener, Asy
// Add image as banner image
else if (resultType == REQUEST_BANNER) {
if (holder.setBanner(this, uri)) {
Point displaySize = new Point();
getWindowManager().getDefaultDisplay().getSize(displaySize);
picasso.load(uri).resize(displaySize.x, displaySize.x / 3).centerCrop(Gravity.TOP).into(profile_banner, this);
int widthPixels = Resources.getSystem().getDisplayMetrics().widthPixels;
picasso.load(uri).resize(widthPixels, widthPixels / 3).centerCrop(Gravity.TOP).into(profile_banner, this);
addBannerBtn.setVisibility(INVISIBLE);
changeBannerBtn.setVisibility(VISIBLE);
} else {

View File

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

View File

@ -28,11 +28,6 @@ public class NetworkAdapter extends BaseAdapter {
*/
public static final int ID_MASTODON = 20;
/**
* social network icons
*/
private static final int[] ICONS = {R.drawable.mastodon, R.drawable.twitter};
/**
* social network names
*/
@ -55,7 +50,7 @@ public class NetworkAdapter extends BaseAdapter {
@Override
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.setText(STRINGS[position]);
textItem.setCompoundDrawablesWithIntrinsicBounds(ICONS[position], 0, 0, 0);
textItem.setTextColor(settings.getTextColor());
textItem.setBackgroundColor(settings.getCardColor());
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
android:id="@+id/page_image_gif"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/page_image_toolbar"
app:layout_constraintBottom_toBottomOf="parent"
@ -48,4 +48,15 @@
app:layout_constraintBottom_toBottomOf="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>

View File

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