From 7c1924178711c721b959e72cf2c13b2cc13863d6 Mon Sep 17 00:00:00 2001 From: nuclearfog Date: Fri, 10 Mar 2023 17:38:44 +0100 Subject: [PATCH] version upgrade, bug fix, moved notification dismiss to notification list fragment, added poll edit dialog --- app/build.gradle | 4 +- .../twidda/backend/async/AsyncExecutor.java | 10 ++- .../backend/async/NotificationAction.java | 30 +++---- .../backend/async/NotificationLoader.java | 16 ++-- .../twidda/backend/helper/StatusUpdate.java | 2 +- .../ui/activities/SettingsActivity.java | 2 +- .../twidda/ui/activities/StatusActivity.java | 38 +++------ .../ui/activities/UserlistActivity.java | 3 +- .../twidda/ui/adapter/EditOptionsAdapter.java | 42 ++++++++++ .../ui/adapter/NotificationAdapter.java | 29 +++++-- .../adapter/holder/OnHolderClickListener.java | 2 + .../ui/adapter/holder/StatusHolder.java | 8 ++ .../twidda/ui/adapter/holder/UserHolder.java | 14 +++- .../twidda/ui/dialogs/ConnectionDialog.java | 2 +- .../twidda/ui/dialogs/PollDialog.java | 29 +++++++ .../ui/fragments/NotificationFragment.java | 82 +++++++++++++++---- app/src/main/res/layout/dialog_poll.xml | 71 ++++++++++++++++ app/src/main/res/layout/item_status.xml | 18 +++- app/src/main/res/layout/item_user.xml | 18 +++- app/src/main/res/menu/status.xml | 5 -- app/src/main/res/values/dimens.xml | 8 ++ app/src/main/res/values/strings.xml | 4 + app/src/main/res/values/styles.xml | 5 ++ 23 files changed, 353 insertions(+), 89 deletions(-) create mode 100644 app/src/main/java/org/nuclearfog/twidda/ui/adapter/EditOptionsAdapter.java create mode 100644 app/src/main/java/org/nuclearfog/twidda/ui/dialogs/PollDialog.java create mode 100644 app/src/main/res/layout/dialog_poll.xml diff --git a/app/build.gradle b/app/build.gradle index 8f23e589..38c9b592 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId 'org.nuclearfog.twidda' minSdkVersion 21 targetSdkVersion 33 - versionCode 75 - versionName '3.0.7' + versionCode 76 + versionName '3.0.8' resConfigs 'en', 'de-rDE', 'zh-rCN' } diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/async/AsyncExecutor.java b/app/src/main/java/org/nuclearfog/twidda/backend/async/AsyncExecutor.java index 96f1699d..34a5ca08 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/async/AsyncExecutor.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/async/AsyncExecutor.java @@ -10,9 +10,10 @@ import androidx.annotation.WorkerThread; import java.lang.ref.WeakReference; import java.util.Queue; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * Executor implementation used to run tasks asynchronously @@ -26,10 +27,15 @@ public abstract class AsyncExecutor { */ private static final int N_THREAD = 4; + /** + * timeout for queued processes + */ + private static final long P_TIMEOUT = 5000L; + /** * thread pool executor */ - private static final ExecutorService THREAD_POOL = Executors.newFixedThreadPool(N_THREAD); + private static final ExecutorService THREAD_POOL = new ThreadPoolExecutor(1, N_THREAD, P_TIMEOUT, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); /** * handler used to send result back to activity/fragment diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/async/NotificationAction.java b/app/src/main/java/org/nuclearfog/twidda/backend/async/NotificationAction.java index 994d5e26..e7e22c34 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/async/NotificationAction.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/async/NotificationAction.java @@ -16,7 +16,7 @@ import org.nuclearfog.twidda.model.Notification; * * @author nuclearfog */ -public class NotificationAction extends AsyncExecutor { +public class NotificationAction extends AsyncExecutor { private Connection connection; private AppDatabase db; @@ -32,39 +32,39 @@ public class NotificationAction extends AsyncExecutor { +public class NotificationLoader extends AsyncExecutor { private Connection connection; private AppDatabase db; @@ -35,7 +35,7 @@ public class NotificationLoader extends AsyncExecutor result = null; try { if (params.minId == 0L && params.maxId == 0L) { @@ -51,22 +51,22 @@ public class NotificationLoader extends AsyncExecutor notifications, int position, @Nullable ConnectionException exception) { + NotificationLoaderResult(@Nullable List notifications, int position, @Nullable ConnectionException exception) { this.notifications = notifications; this.exception = exception; this.position = position; diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/helper/StatusUpdate.java b/app/src/main/java/org/nuclearfog/twidda/backend/helper/StatusUpdate.java index 55661d35..4ac5435e 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/helper/StatusUpdate.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/helper/StatusUpdate.java @@ -202,7 +202,7 @@ public class StatusUpdate { * get type of attachment * currently there is only one type of media used at once * - * @return media type {@link #EMPTY ,#MEDIA_VIDEO,#MEDIA_IMAGE,#MEDIA_GIF} + * @return media type {@link #EMPTY,#MEDIA_VIDEO,#MEDIA_IMAGE,#MEDIA_GIF} */ public int getAttachmentType() { return attachment; diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/activities/SettingsActivity.java b/app/src/main/java/org/nuclearfog/twidda/ui/activities/SettingsActivity.java index 4a8785dc..a309461b 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/activities/SettingsActivity.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/activities/SettingsActivity.java @@ -602,7 +602,7 @@ public class SettingsActivity extends AppCompatActivity implements OnClickListen if (result.locations != null) { locationAdapter.replaceItems(result.locations); int position = locationAdapter.indexOf(settings.getTrendLocation()); - if (position > 0) + if (position >= 0) locationSpinner.setSelection(position, false); locationSpinner.setOnItemSelectedListener(this); } else { diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/activities/StatusActivity.java b/app/src/main/java/org/nuclearfog/twidda/ui/activities/StatusActivity.java index 76175b86..e252727a 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/activities/StatusActivity.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/activities/StatusActivity.java @@ -50,8 +50,8 @@ import org.nuclearfog.textviewtool.LinkAndScrollMovement; import org.nuclearfog.twidda.R; import org.nuclearfog.twidda.backend.api.ConnectionException; import org.nuclearfog.twidda.backend.async.NotificationAction; -import org.nuclearfog.twidda.backend.async.NotificationAction.NotificationParam; -import org.nuclearfog.twidda.backend.async.NotificationAction.NotificationResult; +import org.nuclearfog.twidda.backend.async.NotificationAction.NotificationActionParam; +import org.nuclearfog.twidda.backend.async.NotificationAction.NotificationActionResult; import org.nuclearfog.twidda.backend.async.StatusAction; import org.nuclearfog.twidda.backend.async.StatusAction.StatusParam; import org.nuclearfog.twidda.backend.async.StatusAction.StatusResult; @@ -62,7 +62,6 @@ import org.nuclearfog.twidda.backend.utils.AppStyles; import org.nuclearfog.twidda.backend.utils.ErrorHandler; import org.nuclearfog.twidda.backend.utils.PicassoBuilder; import org.nuclearfog.twidda.backend.utils.StringTools; -import org.nuclearfog.twidda.config.Configuration; import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.database.impl.DatabaseNotification; import org.nuclearfog.twidda.database.impl.DatabaseStatus; @@ -325,7 +324,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener super.onStart(); if (notification != null) { if (notification instanceof DatabaseNotification) { - NotificationParam param = new NotificationParam(NotificationParam.ONLINE, notification.getId()); + NotificationActionParam param = new NotificationActionParam(NotificationActionParam.ONLINE, notification.getId()); notificationAsync.execute(param, this::onNotificationResult); } } else if (status != null) { @@ -343,7 +342,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener StatusParam param = new StatusParam(StatusParam.DATABASE, statusId); statusAsync.execute(param, this::onStatusResult); } else if (notificationId != 0L) { - NotificationParam param = new NotificationParam(NotificationParam.ONLINE, notificationId); + NotificationActionParam param = new NotificationActionParam(NotificationActionParam.ONLINE, notificationId); notificationAsync.execute(param, this::onNotificationResult); } } @@ -393,15 +392,9 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener MenuItem optHide = m.findItem(R.id.menu_status_hide); MenuItem optCopy = m.findItem(R.id.menu_status_copy); MenuItem optMetrics = m.findItem(R.id.menu_status_metrics); - MenuItem optDismiss = m.findItem(R.id.menu_notification_dismiss); MenuItem menuBookmark = m.findItem(R.id.menu_status_bookmark); SubMenu copyMenu = optCopy.getSubMenu(); - Configuration config = settings.getLogin().getConfiguration(); - // set notification options - if (notification != null) { - optDismiss.setVisible(config.NotificationDismissEnabled()); - } // set status options if (status != null) { Status currentStatus = status; @@ -498,10 +491,6 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener metricsDialog.show(status.getMetrics()); } } - // open notification dismiss dialog - else if (item.getItemId() == R.id.menu_notification_dismiss) { - confirmDialog.show(ConfirmDialog.NOTIFICATION_DISMISS); - } // copy media links else if (item.getGroupId() == MENU_GROUP_COPY) { int index = item.getItemId(); @@ -661,13 +650,6 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener } } break; - - case ConfirmDialog.NOTIFICATION_DISMISS: - if (notification != null) { - NotificationParam param = new NotificationParam(NotificationParam.DISMISS, notification.getId()); - notificationAsync.execute(param, this::onNotificationResult); - } - break; } } @@ -970,23 +952,23 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener * * @param result notification containing status information */ - public void onNotificationResult(NotificationResult result) { + public void onNotificationResult(NotificationActionResult result) { switch (result.mode) { - case NotificationResult.DATABASE: + case NotificationActionResult.DATABASE: if (result.notification != null) { - NotificationParam param = new NotificationParam(NotificationParam.ONLINE, result.notification.getId()); + NotificationActionParam param = new NotificationActionParam(NotificationActionParam.ONLINE, result.notification.getId()); notificationAsync.execute(param, this::onNotificationResult); } // fall through - case NotificationResult.ONLINE: + case NotificationActionResult.ONLINE: if (result.notification != null && result.notification.getStatus() != null) { notification = result.notification; setStatus(result.notification.getStatus()); } break; - case NotificationResult.DISMISS: + case NotificationActionResult.DISMISS: if (notification != null) { Intent intent = new Intent(); intent.putExtra(INTENT_NOTIFICATION_REMOVED_ID, notification.getId()); @@ -996,7 +978,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener finish(); break; - case NotificationResult.ERROR: + case NotificationActionResult.ERROR: String message = ErrorHandler.getErrorMessage(this, result.exception); Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show(); if (notification == null) { diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/activities/UserlistActivity.java b/app/src/main/java/org/nuclearfog/twidda/ui/activities/UserlistActivity.java index 0e0a7c5a..7d502975 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/activities/UserlistActivity.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/activities/UserlistActivity.java @@ -92,8 +92,9 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul /** * regex pattern to validate username + * e.g. username, @username or @username@instance.social */ - private static final Pattern USERNAME_PATTERN = Pattern.compile("@?\\w{1,15}"); + private static final Pattern USERNAME_PATTERN = Pattern.compile("@?[\\w\\d]{1,20}(@[\\w\\d.]{1,50})?"); private ActivityResultLauncher activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this); diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/EditOptionsAdapter.java b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/EditOptionsAdapter.java new file mode 100644 index 00000000..f575c727 --- /dev/null +++ b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/EditOptionsAdapter.java @@ -0,0 +1,42 @@ +package org.nuclearfog.twidda.ui.adapter; + +import android.content.Context; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.Adapter; + +/** + * + */ +public class EditOptionsAdapter extends Adapter { + + + public EditOptionsAdapter(Context context) {} + + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return null; + } + + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + + } + + + @Override + public int getItemCount() { + return 0; + } + + + public interface OnOptionChangedListener { + + + } +} \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/NotificationAdapter.java b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/NotificationAdapter.java index b7813ff9..0b8f7fd2 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/NotificationAdapter.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/NotificationAdapter.java @@ -145,9 +145,11 @@ public class NotificationAdapter extends Adapter implements OnHolder long sinceId = 0; long maxId = 0; if (index == 0) { - Notification notification = items.get(index + 1); - if (notification != null) { - sinceId = notification.getId(); + if (items.size() > 1) { + Notification notification = items.get(index + 1); + if (notification != null) { + sinceId = notification.getId(); + } } } else if (index == items.size() - 1) { Notification notification = items.get(index - 1); @@ -186,7 +188,13 @@ public class NotificationAdapter extends Adapter implements OnHolder case OnHolderClickListener.STATUS_CLICK: if (item != null) { - listener.onNotificationClick(item); + listener.onNotificationClick(item, OnNotificationClickListener.VIEW); + } + break; + + case OnHolderClickListener.NOTIFICATION_DISMISS: + if (item != null) { + listener.onNotificationClick(item, OnNotificationClickListener.DISMISS); } break; } @@ -269,12 +277,23 @@ public class NotificationAdapter extends Adapter implements OnHolder */ public interface OnNotificationClickListener { + /** + * show a notification + */ + int VIEW = 1; + + /** + * dismiss a notification + */ + int DISMISS = 2; + /** * called on notification click * * @param notification clicked notification + * @param action action {@link #VIEW,#DISMISS} */ - void onNotificationClick(Notification notification); + void onNotificationClick(Notification notification, int action); /** * called on user item click diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/OnHolderClickListener.java b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/OnHolderClickListener.java index e7c78be7..9025e324 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/OnHolderClickListener.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/OnHolderClickListener.java @@ -45,6 +45,8 @@ public interface OnHolderClickListener { int POLL_VOTE = 18; + int NOTIFICATION_DISMISS = 19; + /** * called when an item was clicked * diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/StatusHolder.java b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/StatusHolder.java index 729073a1..5a4f2d60 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/StatusHolder.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/StatusHolder.java @@ -44,6 +44,7 @@ public class StatusHolder extends ViewHolder implements OnClickListener { private ImageView profile, repostUserIcon, verifiedIcon, lockedIcon, repostIcon, favoriteIcon, replyStatus; private TextView username, screenname, text, repost, favorite, reply, reposter, created, replyname, label; + private View dismissButton; private RecyclerView iconList; private GlobalSettings settings; @@ -61,6 +62,7 @@ public class StatusHolder extends ViewHolder implements OnClickListener { CardView cardLayout = (CardView) itemView; ViewGroup container = itemView.findViewById(R.id.item_status_container); label = itemView.findViewById(R.id.item_status_label); + dismissButton = itemView.findViewById(R.id.item_status_notification_dismiss); profile = itemView.findViewById(R.id.item_status_profile_image); verifiedIcon = itemView.findViewById(R.id.item_status_verified_icon); lockedIcon = itemView.findViewById(R.id.item_status_locked_icon); @@ -93,6 +95,7 @@ public class StatusHolder extends ViewHolder implements OnClickListener { label.setOnClickListener(this); itemView.setOnClickListener(this); + dismissButton.setOnClickListener(this); } @@ -104,6 +107,8 @@ public class StatusHolder extends ViewHolder implements OnClickListener { listener.onItemClick(position, OnHolderClickListener.STATUS_CLICK); } else if (v == label) { listener.onItemClick(position, OnHolderClickListener.STATUS_LABEL); + } else if (v == dismissButton) { + listener.onItemClick(position, OnHolderClickListener.NOTIFICATION_DISMISS); } } } @@ -234,6 +239,9 @@ public class StatusHolder extends ViewHolder implements OnClickListener { label.setVisibility(View.VISIBLE); label.setText(text); label.setCompoundDrawablesWithIntrinsicBounds(iconRes, 0, 0, 0); + if (settings.getLogin().getConfiguration().NotificationDismissEnabled()) { + dismissButton.setVisibility(View.VISIBLE); + } AppStyles.setDrawableColor(label, settings.getIconColor()); } } \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/UserHolder.java b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/UserHolder.java index 51066e55..df54972a 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/UserHolder.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/holder/UserHolder.java @@ -40,6 +40,7 @@ public class UserHolder extends ViewHolder implements OnClickListener { private TextView username, screenname, followingCount, followerCount, label; private ImageView profileImg, verifyIcon, lockedIcon; private ImageButton delete; + private View notificationDismiss; private GlobalSettings settings; private Picasso picasso; @@ -56,6 +57,7 @@ public class UserHolder extends ViewHolder implements OnClickListener { CardView background = (CardView) itemView; ViewGroup container = itemView.findViewById(R.id.item_user_container); label = itemView.findViewById(R.id.item_user_label); + notificationDismiss = itemView.findViewById(R.id.item_user_notification_dismiss); username = itemView.findViewById(R.id.item_user_username); screenname = itemView.findViewById(R.id.item_user_screenname); followingCount = itemView.findViewById(R.id.item_user_following_count); @@ -74,6 +76,7 @@ public class UserHolder extends ViewHolder implements OnClickListener { } itemView.setOnClickListener(this); + notificationDismiss.setOnClickListener(this); delete.setOnClickListener(this); } @@ -86,6 +89,8 @@ public class UserHolder extends ViewHolder implements OnClickListener { listener.onItemClick(position, OnHolderClickListener.USER_CLICK); } else if (v == delete) { listener.onItemClick(position, OnHolderClickListener.USER_REMOVE); + } else if (v == notificationDismiss) { + listener.onItemClick(position, OnHolderClickListener.NOTIFICATION_DISMISS); } } } @@ -126,11 +131,11 @@ public class UserHolder extends ViewHolder implements OnClickListener { int iconRes; String text, name; Resources resources = itemView.getResources(); - if (notification.getUser() != null) + if (notification.getUser() != null) { name = notification.getUser().getScreenname(); - else + } else { name = ""; - + } switch (notification.getType()) { default: text = ""; @@ -147,6 +152,9 @@ public class UserHolder extends ViewHolder implements OnClickListener { iconRes = R.drawable.follower_request; break; } + if (settings.getLogin().getConfiguration().NotificationDismissEnabled()) { + notificationDismiss.setVisibility(VISIBLE); + } label.setVisibility(VISIBLE); label.setCompoundDrawablesWithIntrinsicBounds(iconRes, 0, 0, 0); label.setText(text); diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/dialogs/ConnectionDialog.java b/app/src/main/java/org/nuclearfog/twidda/ui/dialogs/ConnectionDialog.java index b86234ef..1719c495 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/dialogs/ConnectionDialog.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/dialogs/ConnectionDialog.java @@ -55,7 +55,7 @@ public class ConnectionDialog extends Dialog implements OnCheckedChangeListener, api1 = findViewById(R.id.dialog_connection_api1); api2 = findViewById(R.id.dialog_connection_api2); - int width = (int) (context.getResources().getDisplayMetrics().widthPixels * 0.9); + int width = (int) (context.getResources().getDisplayMetrics().widthPixels * 0.9f); getWindow().setLayout(width, WRAP_CONTENT); AppStyles.setTheme(root); enableApi.setOnCheckedChangeListener(this); diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/dialogs/PollDialog.java b/app/src/main/java/org/nuclearfog/twidda/ui/dialogs/PollDialog.java new file mode 100644 index 00000000..2888b8af --- /dev/null +++ b/app/src/main/java/org/nuclearfog/twidda/ui/dialogs/PollDialog.java @@ -0,0 +1,29 @@ +package org.nuclearfog.twidda.ui.dialogs; + +import android.app.Dialog; +import android.content.Context; + +import androidx.annotation.NonNull; + +import org.nuclearfog.twidda.R; +import org.nuclearfog.twidda.backend.helper.PollUpdate; + +/** + * Dialog class used to show poll editor + * + * @author nuclearfog + */ +public class PollDialog extends Dialog { + + + public PollDialog(@NonNull Context context) { + super(context, R.style.PollDialog); + setContentView(R.layout.dialog_poll); + } + + + + public void show(@NonNull PollUpdate poll) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/fragments/NotificationFragment.java b/app/src/main/java/org/nuclearfog/twidda/ui/fragments/NotificationFragment.java index 39029e0c..6bd9a103 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/fragments/NotificationFragment.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/fragments/NotificationFragment.java @@ -12,10 +12,14 @@ import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.nuclearfog.twidda.backend.api.ConnectionException; import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback; +import org.nuclearfog.twidda.backend.async.NotificationAction; +import org.nuclearfog.twidda.backend.async.NotificationAction.NotificationActionParam; +import org.nuclearfog.twidda.backend.async.NotificationAction.NotificationActionResult; import org.nuclearfog.twidda.backend.async.NotificationLoader; -import org.nuclearfog.twidda.backend.async.NotificationLoader.NotificationParam; -import org.nuclearfog.twidda.backend.async.NotificationLoader.NotificationResult; +import org.nuclearfog.twidda.backend.async.NotificationLoader.NotificationLoaderParam; +import org.nuclearfog.twidda.backend.async.NotificationLoader.NotificationLoaderResult; import org.nuclearfog.twidda.backend.utils.ErrorHandler; import org.nuclearfog.twidda.model.Notification; import org.nuclearfog.twidda.model.User; @@ -23,36 +27,47 @@ import org.nuclearfog.twidda.ui.activities.ProfileActivity; import org.nuclearfog.twidda.ui.activities.StatusActivity; import org.nuclearfog.twidda.ui.adapter.NotificationAdapter; import org.nuclearfog.twidda.ui.adapter.NotificationAdapter.OnNotificationClickListener; +import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog; +import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog.OnConfirmListener; /** * fragment to show notifications * * @author nuclearfog */ -public class NotificationFragment extends ListFragment implements OnNotificationClickListener, AsyncCallback, ActivityResultCallback { +public class NotificationFragment extends ListFragment implements OnNotificationClickListener, OnConfirmListener, + AsyncCallback, ActivityResultCallback { private ActivityResultLauncher activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this); - private NotificationLoader notificationAsync; + private NotificationLoader notificationLoader; + private NotificationAction notificationAction; private NotificationAdapter adapter; + private ConfirmDialog confirmDialog; + + private Notification select; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + confirmDialog = new ConfirmDialog(requireContext()); + notificationLoader = new NotificationLoader(requireContext()); + notificationAction = new NotificationAction(requireContext()); adapter = new NotificationAdapter(requireContext(), this); - notificationAsync = new NotificationLoader(requireContext()); setAdapter(adapter); + confirmDialog.setConfirmListener(this); load(0L, 0L, 0); setRefresh(true); } @Override - public void onDestroyView() { - notificationAsync.cancel(); - super.onDestroyView(); + public void onDestroy() { + notificationLoader.cancel(); + notificationAction.cancel(); + super.onDestroy(); } @@ -75,11 +90,20 @@ public class NotificationFragment extends ListFragment implements OnNotification @Override - public void onNotificationClick(Notification notification) { + public void onNotificationClick(Notification notification, int action) { if (!isRefreshing()) { - Intent intent = new Intent(requireContext(), StatusActivity.class); - intent.putExtra(StatusActivity.KEY_NOTIFICATION_DATA, notification); - activityResultLauncher.launch(intent); + switch (action) { + case OnNotificationClickListener.VIEW: + Intent intent = new Intent(requireContext(), StatusActivity.class); + intent.putExtra(StatusActivity.KEY_NOTIFICATION_DATA, notification); + activityResultLauncher.launch(intent); + break; + + case OnNotificationClickListener.DISMISS: + confirmDialog.show(ConfirmDialog.NOTIFICATION_DISMISS); + select = notification; + break; + } } } @@ -96,7 +120,7 @@ public class NotificationFragment extends ListFragment implements OnNotification @Override public boolean onPlaceholderClick(long sinceId, long maxId, int position) { - if (notificationAsync.isIdle()) { + if (notificationLoader.isIdle()) { load(sinceId, maxId, position); return true; } @@ -127,7 +151,7 @@ public class NotificationFragment extends ListFragment implements OnNotification @Override - public void onResult(NotificationResult result) { + public void onResult(NotificationLoaderResult result) { if (result.notifications != null) { adapter.addItems(result.notifications, result.position); } else if (getContext() != null) { @@ -138,13 +162,39 @@ public class NotificationFragment extends ListFragment implements OnNotification setRefresh(false); } + + @Override + public void onConfirm(int type, boolean rememberChoice) { + if (type == ConfirmDialog.NOTIFICATION_DISMISS) { + if (select != null) { + NotificationActionParam param = new NotificationActionParam(NotificationActionParam.DISMISS, select.getId()); + notificationAction.execute(param, this::ondismiss); + } + } + } + + /** + * + */ + public void ondismiss(NotificationActionResult result) { + if (result.mode == NotificationActionResult.DISMISS) { + adapter.removeItem(result.id); + } else if (result.mode == NotificationActionResult.ERROR) { + String message = ErrorHandler.getErrorMessage(getContext(), result.exception); + Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show(); + if (result.exception != null && result.exception.getErrorCode() == ConnectionException.RESOURCE_NOT_FOUND) { + adapter.removeItem(result.id); + } + } + } + /** * @param minId lowest notification ID to load * @param maxId highest notification Id to load * @param pos index to insert the new items */ private void load(long minId, long maxId, int pos) { - NotificationParam param = new NotificationParam(pos, minId, maxId); - notificationAsync.execute(param, this); + NotificationLoaderParam param = new NotificationLoaderParam(pos, minId, maxId); + notificationLoader.execute(param, this); } } \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_poll.xml b/app/src/main/res/layout/dialog_poll.xml new file mode 100644 index 00000000..1c48f119 --- /dev/null +++ b/app/src/main/res/layout/dialog_poll.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_status.xml b/app/src/main/res/layout/item_status.xml index 10581fa7..88d13ce4 100644 --- a/app/src/main/res/layout/item_status.xml +++ b/app/src/main/res/layout/item_status.xml @@ -24,7 +24,23 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@id/item_status_label_barrier" - app:layout_constraintEnd_toEndOf="parent" /> + app:layout_constraintEnd_toStartOf="@id/item_status_notification_dismiss" /> + + + app:layout_constraintEnd_toStartOf="@id/item_user_notification_dismiss"/> + + - - 5dp 8dp 5dp + 20sp + 1dp 12sp 12sp 12sp @@ -98,6 +100,8 @@ 5dp 5dp 36dp + @dimen/item_status_notification_button_size + @dimen/item_status_notification_button_drawable_padding 7dp 12sp 14sp @@ -236,6 +240,10 @@ 8dp 13sp + + 3dp + 18sp + 22sp 11sp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5f709f2f..10f5485e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -213,6 +213,7 @@ discard changes? Image preview add new image + dismiss notification share status close editor Link @@ -220,6 +221,9 @@ Location Bio discard + create poll + Duration: + count discard changes? User data follows you diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 98195c38..9b2ec4c5 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -49,6 +49,11 @@ 80% + +