Loading app/build.gradle +3 −1 Original line number Diff line number Diff line Loading @@ -68,13 +68,15 @@ android { 'src/main/res/layouts/mastodon', 'src/main/res/layouts/peertube', 'src/main/res/layouts', 'src/main/layout', 'src/main/res/drawables/mastodon', 'src/main/res/drawables/peertube', 'src/main/res/drawables', 'src/main/res/menus/mastodon', 'src/main/res/menus/peertube', 'src/main/res/menus', 'src/main/res' ] } Loading app/src/main/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,9 @@ <activity android:name=".mastodon.activities.ContextActivity" android:configChanges="keyboardHidden|orientation|screenSize" /> <activity android:name=".mastodon.activities.DirectMessageActivity" android:configChanges="keyboardHidden|orientation|screenSize" /> <activity android:name=".mastodon.activities.DraftActivity" android:configChanges="keyboardHidden|orientation|screenSize" /> Loading app/src/main/java/app/fedilab/android/mastodon/activities/DirectMessageActivity.java 0 → 100644 +131 −0 Original line number Diff line number Diff line package app.fedilab.android.mastodon.activities; /* Copyright 2023 Thomas Schneider * * This file is a part of Fedilab * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see <http://www.gnu.org/licenses>. */ import static app.fedilab.android.BaseMainActivity.currentAccount; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.TypedValue; import android.view.MenuItem; import androidx.appcompat.app.ActionBar; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.preference.PreferenceManager; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.databinding.ActivityDirectMessageBinding; import app.fedilab.android.mastodon.client.entities.api.Status; import app.fedilab.android.mastodon.client.entities.app.StatusCache; import app.fedilab.android.mastodon.exception.DBException; import app.fedilab.android.mastodon.helper.Helper; import app.fedilab.android.mastodon.helper.MastodonHelper; import app.fedilab.android.mastodon.ui.drawer.StatusAdapter; import app.fedilab.android.mastodon.ui.fragment.timeline.FragmentMastodonDirectMessage; import app.fedilab.android.mastodon.viewmodel.mastodon.StatusesVM; public class DirectMessageActivity extends BaseActivity implements FragmentMastodonDirectMessage.FirstMessage { public static boolean expand; public static boolean displayCW; Fragment currentFragment; private Status firstMessage; private String remote_instance; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityDirectMessageBinding binding = ActivityDirectMessageBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setSupportActionBar(binding.toolbar); ActionBar actionBar = getSupportActionBar(); //Remove title if (actionBar != null) { actionBar.setDisplayShowTitleEnabled(false); } binding.title.setText(R.string.context_conversation); SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(this); float scale = sharedpreferences.getFloat(getString(R.string.SET_FONT_SCALE), 1.1f); binding.title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18 * 1.1f / scale); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true); } Bundle b = getIntent().getExtras(); displayCW = sharedpreferences.getBoolean(getString(R.string.SET_EXPAND_CW), false); Status focusedStatus = null; // or other values if (b != null) { focusedStatus = (Status) b.getSerializable(Helper.ARG_STATUS); remote_instance = b.getString(Helper.ARG_REMOTE_INSTANCE, null); } if (focusedStatus == null || currentAccount == null || currentAccount.mastodon_account == null) { finish(); return; } MastodonHelper.loadPPMastodon(binding.profilePicture, currentAccount.mastodon_account); Bundle bundle = new Bundle(); bundle.putSerializable(Helper.ARG_STATUS, focusedStatus); bundle.putString(Helper.ARG_REMOTE_INSTANCE, remote_instance); FragmentMastodonDirectMessage FragmentMastodonDirectMessage = new FragmentMastodonDirectMessage(); FragmentMastodonDirectMessage.firstMessage = this; currentFragment = Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_content_main, FragmentMastodonDirectMessage, bundle, null, null); StatusesVM timelinesVM = new ViewModelProvider(DirectMessageActivity.this).get(StatusesVM.class); timelinesVM.getStatus(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, focusedStatus.id).observe(DirectMessageActivity.this, status -> { if (status != null) { StatusCache statusCache = new StatusCache(); statusCache.instance = BaseMainActivity.currentInstance; statusCache.user_id = BaseMainActivity.currentUserID; statusCache.status = status; statusCache.status_id = status.id; //Update cache new Thread(() -> { try { new StatusCache(getApplication()).updateIfExists(statusCache); Handler mainHandler = new Handler(Looper.getMainLooper()); //Update UI Runnable myRunnable = () -> StatusAdapter.sendAction(DirectMessageActivity.this, Helper.ARG_STATUS_ACTION, status, null); mainHandler.post(myRunnable); } catch (DBException e) { e.printStackTrace(); } }).start(); } }); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return true; } @Override public void get(Status status) { firstMessage = status; invalidateOptionsMenu(); } } No newline at end of file app/src/main/java/app/fedilab/android/mastodon/ui/drawer/ConversationAdapter.java +14 −2 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import app.fedilab.android.R; import app.fedilab.android.databinding.DrawerConversationBinding; import app.fedilab.android.databinding.ThumbnailBinding; import app.fedilab.android.mastodon.activities.ContextActivity; import app.fedilab.android.mastodon.activities.DirectMessageActivity; import app.fedilab.android.mastodon.client.entities.api.Account; import app.fedilab.android.mastodon.client.entities.api.Attachment; import app.fedilab.android.mastodon.client.entities.api.Conversation; Loading Loading @@ -210,15 +211,26 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH //--- DATE --- holder.binding.lastMessageDate.setText(Helper.dateDiff(context, conversation.last_status.created_at)); boolean chatMode = sharedpreferences.getBoolean(context.getString(R.string.SET_CHAT_FOR_CONVERSATION), true); holder.binding.statusContent.setOnClickListener(v -> { Intent intent = new Intent(context, ContextActivity.class); Intent intent; if (chatMode) { intent = new Intent(context, DirectMessageActivity.class); } else { intent = new Intent(context, ContextActivity.class); } intent.putExtra(Helper.ARG_STATUS, conversation.last_status); context.startActivity(intent); }); holder.binding.attachmentsListContainer.setOnTouchListener((v, event) -> { if (event.getAction() == MotionEvent.ACTION_UP) { Intent intent = new Intent(context, ContextActivity.class); Intent intent; if (chatMode) { intent = new Intent(context, DirectMessageActivity.class); } else { intent = new Intent(context, ContextActivity.class); } intent.putExtra(Helper.ARG_STATUS, conversation.last_status); context.startActivity(intent); } Loading app/src/main/java/app/fedilab/android/mastodon/ui/drawer/StatusDirectMessageAdapter.java 0 → 100644 +106 −0 Original line number Diff line number Diff line package app.fedilab.android.mastodon.ui.drawer; /* Copyright 2023 Thomas Schneider * * This file is a part of Fedilab * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see <http://www.gnu.org/licenses>. */ import android.content.Context; import android.view.LayoutInflater; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import org.jetbrains.annotations.NotNull; import java.lang.ref.WeakReference; import java.util.List; import app.fedilab.android.R; import app.fedilab.android.activities.MainActivity; import app.fedilab.android.databinding.DrawerStatusChatBinding; import app.fedilab.android.mastodon.client.entities.api.Status; import app.fedilab.android.mastodon.helper.Helper; import app.fedilab.android.mastodon.helper.MastodonHelper; import app.fedilab.android.mastodon.helper.ThemeHelper; public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final List<Status> statusList; private Context context; private RecyclerView mRecyclerView; public StatusDirectMessageAdapter(List<Status> data) { this.statusList = data; } @NotNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) { context = parent.getContext(); DrawerStatusChatBinding itemBinding = DrawerStatusChatBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); return new StatusChatViewHolder(itemBinding); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { StatusChatViewHolder holder = (StatusChatViewHolder) viewHolder; Status status = statusList.get(position); holder.binding.messageContent.setText( status.getSpanContent(context, new WeakReference<>(holder.binding.messageContent), () -> mRecyclerView.post(() -> notifyItemChanged(holder.getBindingAdapterPosition()))), TextView.BufferType.SPANNABLE); MastodonHelper.loadPPMastodon(holder.binding.userPp, status.account); holder.binding.date.setText(Helper.longDateToString(status.created_at)); //Owner account int textColor; if (status.account.id.equals(MainActivity.currentUserID)) { holder.binding.mainContainer.setBackgroundResource(R.drawable.bubble_right_tail); textColor = R.attr.colorOnPrimary; } else { holder.binding.mainContainer.setBackgroundResource(R.drawable.bubble_left_tail); textColor = R.attr.colorOnSecondary; } holder.binding.date.setTextColor(ThemeHelper.getAttColor(context, textColor)); holder.binding.messageContent.setTextColor(ThemeHelper.getAttColor(context, textColor)); holder.binding.userName.setTextColor(ThemeHelper.getAttColor(context, textColor)); } @Override public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); mRecyclerView = recyclerView; } @Override public int getItemCount() { return statusList.size(); } public static class StatusChatViewHolder extends RecyclerView.ViewHolder { DrawerStatusChatBinding binding; StatusChatViewHolder(DrawerStatusChatBinding itemView) { super(itemView.getRoot()); binding = itemView; } } } No newline at end of file Loading
app/build.gradle +3 −1 Original line number Diff line number Diff line Loading @@ -68,13 +68,15 @@ android { 'src/main/res/layouts/mastodon', 'src/main/res/layouts/peertube', 'src/main/res/layouts', 'src/main/layout', 'src/main/res/drawables/mastodon', 'src/main/res/drawables/peertube', 'src/main/res/drawables', 'src/main/res/menus/mastodon', 'src/main/res/menus/peertube', 'src/main/res/menus', 'src/main/res' ] } Loading
app/src/main/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,9 @@ <activity android:name=".mastodon.activities.ContextActivity" android:configChanges="keyboardHidden|orientation|screenSize" /> <activity android:name=".mastodon.activities.DirectMessageActivity" android:configChanges="keyboardHidden|orientation|screenSize" /> <activity android:name=".mastodon.activities.DraftActivity" android:configChanges="keyboardHidden|orientation|screenSize" /> Loading
app/src/main/java/app/fedilab/android/mastodon/activities/DirectMessageActivity.java 0 → 100644 +131 −0 Original line number Diff line number Diff line package app.fedilab.android.mastodon.activities; /* Copyright 2023 Thomas Schneider * * This file is a part of Fedilab * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see <http://www.gnu.org/licenses>. */ import static app.fedilab.android.BaseMainActivity.currentAccount; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.TypedValue; import android.view.MenuItem; import androidx.appcompat.app.ActionBar; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.preference.PreferenceManager; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.databinding.ActivityDirectMessageBinding; import app.fedilab.android.mastodon.client.entities.api.Status; import app.fedilab.android.mastodon.client.entities.app.StatusCache; import app.fedilab.android.mastodon.exception.DBException; import app.fedilab.android.mastodon.helper.Helper; import app.fedilab.android.mastodon.helper.MastodonHelper; import app.fedilab.android.mastodon.ui.drawer.StatusAdapter; import app.fedilab.android.mastodon.ui.fragment.timeline.FragmentMastodonDirectMessage; import app.fedilab.android.mastodon.viewmodel.mastodon.StatusesVM; public class DirectMessageActivity extends BaseActivity implements FragmentMastodonDirectMessage.FirstMessage { public static boolean expand; public static boolean displayCW; Fragment currentFragment; private Status firstMessage; private String remote_instance; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityDirectMessageBinding binding = ActivityDirectMessageBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setSupportActionBar(binding.toolbar); ActionBar actionBar = getSupportActionBar(); //Remove title if (actionBar != null) { actionBar.setDisplayShowTitleEnabled(false); } binding.title.setText(R.string.context_conversation); SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(this); float scale = sharedpreferences.getFloat(getString(R.string.SET_FONT_SCALE), 1.1f); binding.title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18 * 1.1f / scale); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true); } Bundle b = getIntent().getExtras(); displayCW = sharedpreferences.getBoolean(getString(R.string.SET_EXPAND_CW), false); Status focusedStatus = null; // or other values if (b != null) { focusedStatus = (Status) b.getSerializable(Helper.ARG_STATUS); remote_instance = b.getString(Helper.ARG_REMOTE_INSTANCE, null); } if (focusedStatus == null || currentAccount == null || currentAccount.mastodon_account == null) { finish(); return; } MastodonHelper.loadPPMastodon(binding.profilePicture, currentAccount.mastodon_account); Bundle bundle = new Bundle(); bundle.putSerializable(Helper.ARG_STATUS, focusedStatus); bundle.putString(Helper.ARG_REMOTE_INSTANCE, remote_instance); FragmentMastodonDirectMessage FragmentMastodonDirectMessage = new FragmentMastodonDirectMessage(); FragmentMastodonDirectMessage.firstMessage = this; currentFragment = Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_content_main, FragmentMastodonDirectMessage, bundle, null, null); StatusesVM timelinesVM = new ViewModelProvider(DirectMessageActivity.this).get(StatusesVM.class); timelinesVM.getStatus(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, focusedStatus.id).observe(DirectMessageActivity.this, status -> { if (status != null) { StatusCache statusCache = new StatusCache(); statusCache.instance = BaseMainActivity.currentInstance; statusCache.user_id = BaseMainActivity.currentUserID; statusCache.status = status; statusCache.status_id = status.id; //Update cache new Thread(() -> { try { new StatusCache(getApplication()).updateIfExists(statusCache); Handler mainHandler = new Handler(Looper.getMainLooper()); //Update UI Runnable myRunnable = () -> StatusAdapter.sendAction(DirectMessageActivity.this, Helper.ARG_STATUS_ACTION, status, null); mainHandler.post(myRunnable); } catch (DBException e) { e.printStackTrace(); } }).start(); } }); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return true; } @Override public void get(Status status) { firstMessage = status; invalidateOptionsMenu(); } } No newline at end of file
app/src/main/java/app/fedilab/android/mastodon/ui/drawer/ConversationAdapter.java +14 −2 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import app.fedilab.android.R; import app.fedilab.android.databinding.DrawerConversationBinding; import app.fedilab.android.databinding.ThumbnailBinding; import app.fedilab.android.mastodon.activities.ContextActivity; import app.fedilab.android.mastodon.activities.DirectMessageActivity; import app.fedilab.android.mastodon.client.entities.api.Account; import app.fedilab.android.mastodon.client.entities.api.Attachment; import app.fedilab.android.mastodon.client.entities.api.Conversation; Loading Loading @@ -210,15 +211,26 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH //--- DATE --- holder.binding.lastMessageDate.setText(Helper.dateDiff(context, conversation.last_status.created_at)); boolean chatMode = sharedpreferences.getBoolean(context.getString(R.string.SET_CHAT_FOR_CONVERSATION), true); holder.binding.statusContent.setOnClickListener(v -> { Intent intent = new Intent(context, ContextActivity.class); Intent intent; if (chatMode) { intent = new Intent(context, DirectMessageActivity.class); } else { intent = new Intent(context, ContextActivity.class); } intent.putExtra(Helper.ARG_STATUS, conversation.last_status); context.startActivity(intent); }); holder.binding.attachmentsListContainer.setOnTouchListener((v, event) -> { if (event.getAction() == MotionEvent.ACTION_UP) { Intent intent = new Intent(context, ContextActivity.class); Intent intent; if (chatMode) { intent = new Intent(context, DirectMessageActivity.class); } else { intent = new Intent(context, ContextActivity.class); } intent.putExtra(Helper.ARG_STATUS, conversation.last_status); context.startActivity(intent); } Loading
app/src/main/java/app/fedilab/android/mastodon/ui/drawer/StatusDirectMessageAdapter.java 0 → 100644 +106 −0 Original line number Diff line number Diff line package app.fedilab.android.mastodon.ui.drawer; /* Copyright 2023 Thomas Schneider * * This file is a part of Fedilab * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see <http://www.gnu.org/licenses>. */ import android.content.Context; import android.view.LayoutInflater; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import org.jetbrains.annotations.NotNull; import java.lang.ref.WeakReference; import java.util.List; import app.fedilab.android.R; import app.fedilab.android.activities.MainActivity; import app.fedilab.android.databinding.DrawerStatusChatBinding; import app.fedilab.android.mastodon.client.entities.api.Status; import app.fedilab.android.mastodon.helper.Helper; import app.fedilab.android.mastodon.helper.MastodonHelper; import app.fedilab.android.mastodon.helper.ThemeHelper; public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final List<Status> statusList; private Context context; private RecyclerView mRecyclerView; public StatusDirectMessageAdapter(List<Status> data) { this.statusList = data; } @NotNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) { context = parent.getContext(); DrawerStatusChatBinding itemBinding = DrawerStatusChatBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); return new StatusChatViewHolder(itemBinding); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { StatusChatViewHolder holder = (StatusChatViewHolder) viewHolder; Status status = statusList.get(position); holder.binding.messageContent.setText( status.getSpanContent(context, new WeakReference<>(holder.binding.messageContent), () -> mRecyclerView.post(() -> notifyItemChanged(holder.getBindingAdapterPosition()))), TextView.BufferType.SPANNABLE); MastodonHelper.loadPPMastodon(holder.binding.userPp, status.account); holder.binding.date.setText(Helper.longDateToString(status.created_at)); //Owner account int textColor; if (status.account.id.equals(MainActivity.currentUserID)) { holder.binding.mainContainer.setBackgroundResource(R.drawable.bubble_right_tail); textColor = R.attr.colorOnPrimary; } else { holder.binding.mainContainer.setBackgroundResource(R.drawable.bubble_left_tail); textColor = R.attr.colorOnSecondary; } holder.binding.date.setTextColor(ThemeHelper.getAttColor(context, textColor)); holder.binding.messageContent.setTextColor(ThemeHelper.getAttColor(context, textColor)); holder.binding.userName.setTextColor(ThemeHelper.getAttColor(context, textColor)); } @Override public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); mRecyclerView = recyclerView; } @Override public int getItemCount() { return statusList.size(); } public static class StatusChatViewHolder extends RecyclerView.ViewHolder { DrawerStatusChatBinding binding; StatusChatViewHolder(DrawerStatusChatBinding itemView) { super(itemView.getRoot()); binding = itemView; } } } No newline at end of file