aboutsummaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java9
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java10
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java10
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java16
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java10
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java10
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/markdown/ImageAndGifEntry.java17
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/markdown/MarkdownUtils.java9
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/post/Post.java4
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java5
11 files changed, 85 insertions, 17 deletions
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java
index e62f8773..3ad2c699 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CommentActivity.java
@@ -64,8 +64,10 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
import ml.docilealligator.infinityforreddit.databinding.ActivityCommentBinding;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
+import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry;
import ml.docilealligator.infinityforreddit.markdown.ImageAndGifPlugin;
import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils;
+import ml.docilealligator.infinityforreddit.post.Post;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
import okhttp3.ConnectionPool;
@@ -211,7 +213,12 @@ public class CommentActivity extends BaseActivity implements UploadImageEnabledA
ImageAndGifPlugin imageAndGifPlugin = new ImageAndGifPlugin();
Markwon postBodyMarkwon = MarkdownUtils.createFullRedditMarkwon(this,
miscPlugin, imageAndGifPlugin, parentTextColor, parentSpoilerBackgroundColor, null);
- MarkwonAdapter markwonAdapter = MarkdownUtils.createTablesAdapter(this, mGlide);
+ MarkwonAdapter markwonAdapter = MarkdownUtils.createTablesAdapter(new ImageAndGifEntry(this, mGlide, new ImageAndGifEntry.OnItemClickListener() {
+ @Override
+ public void onItemClick(Post.MediaMetadata mediaMetadata) {
+
+ }
+ }));
binding.commentContentMarkdownView.setLayoutManager(new LinearLayoutManagerBugFixed(this));
binding.commentContentMarkdownView.setAdapter(markwonAdapter);
markwonAdapter.setMarkdown(postBodyMarkwon, parentBodyMarkdown);
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java
index d92ecda7..73092f1d 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java
@@ -44,8 +44,10 @@ import ml.docilealligator.infinityforreddit.customviews.SwipeLockInterface;
import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutManager;
import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
+import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry;
import ml.docilealligator.infinityforreddit.markdown.ImageAndGifPlugin;
import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils;
+import ml.docilealligator.infinityforreddit.post.Post;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
public class FullMarkdownActivity extends BaseActivity {
@@ -144,7 +146,13 @@ public class FullMarkdownActivity extends BaseActivity {
Markwon markwon = MarkdownUtils.createFullRedditMarkwon(this,
miscPlugin, imageAndGifPlugin, markdownColor, spoilerBackgroundColor, null);
- MarkwonAdapter markwonAdapter = MarkdownUtils.createTablesAdapter(this, Glide.with(this));
+ MarkwonAdapter markwonAdapter = MarkdownUtils.createTablesAdapter(new ImageAndGifEntry(this, Glide.with(this),
+ new ImageAndGifEntry.OnItemClickListener() {
+ @Override
+ public void onItemClick(Post.MediaMetadata mediaMetadata) {
+
+ }
+ }));
LinearLayoutManagerBugFixed linearLayoutManager = new SwipeLockLinearLayoutManager(this, new SwipeLockInterface() {
@Override
public void lockSwipe() {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java
index 56bef8fb..01acf928 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java
@@ -52,8 +52,10 @@ import ml.docilealligator.infinityforreddit.customviews.SwipeLockInterface;
import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutManager;
import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
+import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry;
import ml.docilealligator.infinityforreddit.markdown.ImageAndGifPlugin;
import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils;
+import ml.docilealligator.infinityforreddit.post.Post;
import ml.docilealligator.infinityforreddit.utils.JSONUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
@@ -181,7 +183,13 @@ public class WikiActivity extends BaseActivity {
markwon = MarkdownUtils.createFullRedditMarkwon(this,
miscPlugin, imageAndGifPlugin, markdownColor, spoilerBackgroundColor, onLinkLongClickListener);
- markwonAdapter = MarkdownUtils.createTablesAdapter(this, mGlide);
+ markwonAdapter = MarkdownUtils.createTablesAdapter(new ImageAndGifEntry(this, mGlide,
+ new ImageAndGifEntry.OnItemClickListener() {
+ @Override
+ public void onItemClick(Post.MediaMetadata mediaMetadata) {
+
+ }
+ }));
LinearLayoutManagerBugFixed linearLayoutManager = new SwipeLockLinearLayoutManager(this, new SwipeLockInterface() {
@Override
public void lockSwipe() {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java
index 30a3068f..63206e06 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostDetailRecyclerViewAdapter.java
@@ -103,6 +103,7 @@ import ml.docilealligator.infinityforreddit.databinding.ItemPostDetailVideoAndGi
import ml.docilealligator.infinityforreddit.databinding.ItemPostDetailVideoAutoplayBinding;
import ml.docilealligator.infinityforreddit.databinding.ItemPostDetailVideoAutoplayLegacyControllerBinding;
import ml.docilealligator.infinityforreddit.fragments.ViewPostDetailFragment;
+import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry;
import ml.docilealligator.infinityforreddit.markdown.ImageAndGifPlugin;
import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils;
import ml.docilealligator.infinityforreddit.post.Post;
@@ -292,7 +293,20 @@ public class PostDetailRecyclerViewAdapter extends RecyclerView.Adapter<Recycler
mImageAndGifPlugin = new ImageAndGifPlugin();
mPostDetailMarkwon = MarkdownUtils.createFullRedditMarkwon(mActivity,
miscPlugin, mImageAndGifPlugin, markdownColor, postSpoilerBackgroundColor, onLinkLongClickListener);
- mMarkwonAdapter = MarkdownUtils.createTablesAdapter(activity, mGlide);
+ mMarkwonAdapter = MarkdownUtils.createTablesAdapter(new ImageAndGifEntry(activity, mGlide, new ImageAndGifEntry.OnItemClickListener() {
+ @Override
+ public void onItemClick(Post.MediaMetadata mediaMetadata) {
+ Intent intent = new Intent(activity, ViewImageOrGifActivity.class);
+ intent.putExtra(ViewImageOrGifActivity.EXTRA_IMAGE_URL_KEY, mediaMetadata.original.url);
+ intent.putExtra(ViewImageOrGifActivity.EXTRA_IS_NSFW, post.isNSFW());
+ intent.putExtra(ViewImageOrGifActivity.EXTRA_SUBREDDIT_OR_USERNAME_KEY, post.getSubredditName());
+ intent.putExtra(ViewImageOrGifActivity.EXTRA_FILE_NAME_KEY, mediaMetadata.fileName);
+ if (canStartActivity) {
+ canStartActivity = false;
+ activity.startActivity(intent);
+ }
+ }
+ }));
mSeparatePostAndComments = separatePostAndComments;
mLegacyAutoplayVideoControllerUI = sharedPreferences.getBoolean(SharedPreferencesUtils.LEGACY_AUTOPLAY_VIDEO_CONTROLLER_UI, false);
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java
index 42f114fd..906f95c4 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java
@@ -34,8 +34,10 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.SwipeLockInterface;
import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutManager;
import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
+import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry;
import ml.docilealligator.infinityforreddit.markdown.ImageAndGifPlugin;
import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils;
+import ml.docilealligator.infinityforreddit.post.Post;
public class RulesRecyclerViewAdapter extends RecyclerView.Adapter<RulesRecyclerViewAdapter.RuleViewHolder> {
private BaseActivity activity;
@@ -141,7 +143,13 @@ public class RulesRecyclerViewAdapter extends RecyclerView.Adapter<RulesRecycler
if (activity.typeface != null) {
shortNameTextView.setTypeface(activity.typeface);
}
- markwonAdapter = MarkdownUtils.createTablesAdapter(activity, Glide.with(activity));
+ markwonAdapter = MarkdownUtils.createTablesAdapter(new ImageAndGifEntry(activity, Glide.with(activity),
+ new ImageAndGifEntry.OnItemClickListener() {
+ @Override
+ public void onItemClick(Post.MediaMetadata mediaMetadata) {
+
+ }
+ }));
SwipeLockLinearLayoutManager swipeLockLinearLayoutManager = new SwipeLockLinearLayoutManager(activity,
new SwipeLockInterface() {
@Override
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java
index e0fd9975..9c438448 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/SidebarFragment.java
@@ -44,8 +44,10 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.CopyTextBottomS
import ml.docilealligator.infinityforreddit.bottomsheetfragments.UrlMenuBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
+import ml.docilealligator.infinityforreddit.markdown.ImageAndGifEntry;
import ml.docilealligator.infinityforreddit.markdown.ImageAndGifPlugin;
import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils;
+import ml.docilealligator.infinityforreddit.post.Post;
import ml.docilealligator.infinityforreddit.subreddit.FetchSubredditData;
import ml.docilealligator.infinityforreddit.subreddit.SubredditData;
import ml.docilealligator.infinityforreddit.subreddit.SubredditViewModel;
@@ -148,7 +150,13 @@ public class SidebarFragment extends Fragment {
ImageAndGifPlugin imageAndGifPlugin = new ImageAndGifPlugin();
Markwon markwon = MarkdownUtils.createFullRedditMarkwon(activity,
miscPlugin, imageAndGifPlugin, markdownColor, spoilerBackgroundColor, onLinkLongClickListener);
- MarkwonAdapter markwonAdapter = MarkdownUtils.createTablesAdapter(activity, Glide.with(this));
+ MarkwonAdapter markwonAdapter = MarkdownUtils.createTablesAdapter(new ImageAndGifEntry(activity, Glide.with(this),
+ new ImageAndGifEntry.OnItemClickListener() {
+ @Override
+ public void onItemClick(Post.MediaMetadata mediaMetadata) {
+
+ }
+ }));
linearLayoutManager = new LinearLayoutManagerBugFixed(activity);
recyclerView.setLayoutManager(linearLayoutManager);
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/ImageAndGifEntry.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/ImageAndGifEntry.java
index 1e5678e1..18834f90 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/ImageAndGifEntry.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/ImageAndGifEntry.java
@@ -21,14 +21,17 @@ import io.noties.markwon.recycler.MarkwonAdapter;
import jp.wasabeef.glide.transformations.BlurTransformation;
import ml.docilealligator.infinityforreddit.activities.BaseActivity;
import ml.docilealligator.infinityforreddit.databinding.MarkdownImageAndGifBlockBinding;
+import ml.docilealligator.infinityforreddit.post.Post;
public class ImageAndGifEntry extends MarkwonAdapter.Entry<ImageAndGifBlock, ImageAndGifEntry.Holder> {
private BaseActivity baseActivity;
private RequestManager glide;
+ private OnItemClickListener onItemClickListener;
- public ImageAndGifEntry(BaseActivity baseActivity, RequestManager glide) {
+ public ImageAndGifEntry(BaseActivity baseActivity, RequestManager glide, OnItemClickListener onItemClickListener) {
this.baseActivity = baseActivity;
this.glide = glide;
+ this.onItemClickListener = onItemClickListener;
}
@NonNull
@@ -39,6 +42,8 @@ public class ImageAndGifEntry extends MarkwonAdapter.Entry<ImageAndGifBlock, Ima
@Override
public void bindHolder(@NonNull Markwon markwon, @NonNull Holder holder, @NonNull ImageAndGifBlock node) {
+ holder.imageAndGifBlock = node;
+
holder.binding.progressBarMarkdownImageAndGifBlock.setVisibility(View.VISIBLE);
RequestBuilder<Drawable> imageRequestBuilder = glide.load(node.mediaMetadata.original.url).listener(holder.requestListener);
@@ -62,6 +67,7 @@ public class ImageAndGifEntry extends MarkwonAdapter.Entry<ImageAndGifBlock, Ima
public class Holder extends MarkwonAdapter.Holder {
MarkdownImageAndGifBlockBinding binding;
RequestListener<Drawable> requestListener;
+ ImageAndGifBlock imageAndGifBlock;
public Holder(@NonNull MarkdownImageAndGifBlockBinding binding) {
super(binding.getRoot());
@@ -81,6 +87,11 @@ public class ImageAndGifEntry extends MarkwonAdapter.Entry<ImageAndGifBlock, Ima
return false;
}
};
+ binding.getRoot().setOnClickListener(view -> {
+ if (imageAndGifBlock != null) {
+ onItemClickListener.onItemClick(imageAndGifBlock.mediaMetadata);
+ }
+ });
}
/*private final RequestListener<Drawable> requestListener = new RequestListener<Drawable>() {
@@ -195,4 +206,8 @@ public class ImageAndGifEntry extends MarkwonAdapter.Entry<ImageAndGifBlock, Ima
}
}*/
}
+
+ public interface OnItemClickListener {
+ void onItemClick(Post.MediaMetadata mediaMetadata);
+ }
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/MarkdownUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/MarkdownUtils.java
index 74d45bd0..f1fc8cdb 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/MarkdownUtils.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/markdown/MarkdownUtils.java
@@ -6,8 +6,6 @@ import android.text.util.Linkify;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.bumptech.glide.RequestManager;
-
import org.commonmark.ext.gfm.tables.TableBlock;
import io.noties.markwon.Markwon;
@@ -23,7 +21,6 @@ import io.noties.markwon.recycler.table.TableEntry;
import io.noties.markwon.recycler.table.TableEntryPlugin;
import me.saket.bettermovementmethod.BetterLinkMovementMethod;
import ml.docilealligator.infinityforreddit.R;
-import ml.docilealligator.infinityforreddit.activities.BaseActivity;
import ml.docilealligator.infinityforreddit.customviews.CustomMarkwonAdapter;
public class MarkdownUtils {
@@ -51,7 +48,7 @@ public class MarkdownUtils {
.usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod()
.setOnLinkLongClickListener(onLinkLongClickListener)))
.usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
- //.usePlugin(imageAndGifPlugin)
+ .usePlugin(imageAndGifPlugin)
.usePlugin(TableEntryPlugin.create(context))
.build();
}
@@ -98,12 +95,12 @@ public class MarkdownUtils {
* Creates a MarkwonAdapter configured with support for tables.
*/
@NonNull
- public static MarkwonAdapter createTablesAdapter(BaseActivity baseActivity, RequestManager glide) {
+ public static MarkwonAdapter createTablesAdapter(ImageAndGifEntry imageAndGifEntry) {
return MarkwonAdapter.builder(R.layout.adapter_default_entry, R.id.text)
.include(TableBlock.class, TableEntry.create(builder -> builder
.tableLayout(R.layout.adapter_table_block, R.id.table_layout)
.textLayoutIsRoot(R.layout.view_table_entry_cell)))
- .include(ImageAndGifBlock.class, new ImageAndGifEntry(baseActivity, glide))
+ .include(ImageAndGifBlock.class, imageAndGifEntry)
.build();
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/post/Post.java b/app/src/main/java/ml/docilealligator/infinityforreddit/post/Post.java
index e91062b2..a7cb137b 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/post/Post.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/post/Post.java
@@ -1,5 +1,6 @@
package ml.docilealligator.infinityforreddit.post;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -771,12 +772,15 @@ public class Post implements Parcelable {
public String id;
//E.g. Image
public String e;
+ public String fileName;
public MediaItem original;
public MediaItem downscaled;
public MediaMetadata(String id, String e, MediaItem original, MediaItem downscaled) {
this.id = id;
this.e = e;
+ String path = Uri.parse(original.url).getPath();
+ this.fileName = path == null ? "Image.jpg" : path.substring(1);
this.original = original;
this.downscaled = downscaled;
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java b/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java
index d247ad4c..c2152229 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/services/DownloadMediaService.java
@@ -267,7 +267,7 @@ public class DownloadMediaService extends Service {
} else {
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, destinationFileName);
- contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mediaType == EXTRA_MEDIA_TYPE_VIDEO ? "video/*" : "image/*");
+ contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mediaType == EXTRA_MEDIA_TYPE_VIDEO ? "video/mpeg" : "image/jpeg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, destinationFileUriString);
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 1);
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java
index ed88d6f9..f5f3b163 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/Utils.java
@@ -150,8 +150,7 @@ public final class Utils {
}
public static String parseInlineRedditImages(String markdown) {
- return markdown;
- /*StringBuilder markdownStringBuilder = new StringBuilder(markdown);
+ StringBuilder markdownStringBuilder = new StringBuilder(markdown);
Pattern inlineRedditImagePattern = REGEX_PATTERNS[6];
Matcher matcher = inlineRedditImagePattern.matcher(markdownStringBuilder);
int start = 0;
@@ -162,7 +161,7 @@ public final class Utils {
matcher = inlineRedditImagePattern.matcher(markdownStringBuilder);
}
- return markdownStringBuilder.toString();*/
+ return markdownStringBuilder.toString();
}
public static String trimTrailingWhitespace(String source) {