From 83d123e3418d63cddec1fe0161e1df3460c52a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Fri, 22 Nov 2019 22:41:40 +0100 Subject: [PATCH] [UI] New notifications view. --- .../modules/notification/NotificationDao.kt | 5 +- .../notifications/NotificationsAdapter.java | 104 ------------------ .../notifications/NotificationsAdapter.kt | 72 ++++++++++++ .../notifications/NotificationsFragment.java | 65 ----------- .../notifications/NotificationsFragment.kt | 90 +++++++++++++++ .../utils/SimpleDividerItemDecoration.java | 41 +++++++ app/src/main/res/drawable/divider.xml | 15 +++ .../main/res/drawable/ic_no_notifications.xml | 37 +++++++ .../res/layout/fragment_notifications.xml | 30 ++--- .../res/layout/row_notifications_item.xml | 86 ++++----------- app/src/main/res/values/strings.xml | 2 + 11 files changed, 296 insertions(+), 251 deletions(-) delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsAdapter.java create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsAdapter.kt delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsFragment.java create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsFragment.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/utils/SimpleDividerItemDecoration.java create mode 100644 app/src/main/res/drawable/divider.xml create mode 100644 app/src/main/res/drawable/ic_no_notifications.xml diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/notification/NotificationDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/notification/NotificationDao.kt index c08e7e6d..ee666240 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/notification/NotificationDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/notification/NotificationDao.kt @@ -21,7 +21,10 @@ interface NotificationDao { @Query("DELETE FROM notifications WHERE profileId = :profileId") fun clear(profileId: Int) - @Query("SELECT * FROM notifications") + @Query("DELETE FROM notifications") + fun clearAll() + + @Query("SELECT * FROM notifications ORDER BY addedDate DESC") fun getAll(): LiveData> @Query("SELECT * FROM notifications") diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsAdapter.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsAdapter.java deleted file mode 100644 index f54810b9..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsAdapter.java +++ /dev/null @@ -1,104 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.notifications; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.cardview.widget.CardView; -import androidx.recyclerview.widget.RecyclerView; - -import java.util.List; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.utils.models.Date; -import pl.szczodrzynski.edziennik.utils.models.Notification; - -import static pl.szczodrzynski.edziennik.utils.Utils.d; - -public class NotificationsAdapter extends RecyclerView.Adapter { - private static final String TAG = "NotificationsAdapter"; - private Context context; - private List notificationList; - - //getting the context and product list with constructor - public NotificationsAdapter(Context mCtx, List notificationList) { - this.context = mCtx; - this.notificationList = notificationList; - } - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - //inflating and returning our view holder - LayoutInflater inflater = LayoutInflater.from(context); - View view = inflater.inflate(R.layout.row_notifications_item, parent, false); - return new ViewHolder(view); - } - - @Override - public void onBindViewHolder(@NonNull ViewHolder holder, int position) { - App app = (App) context.getApplicationContext(); - - Notification notification = notificationList.get(position); - - holder.notificationsItemDate.setText(Date.fromMillis(notification.addedDate).getFormattedString()); - holder.notificationsItemText.setText(notification.text); - holder.notificationsItemTitle.setText(notification.title); - holder.notificationsItemType.setText(Notification.stringType(context, notification.type)); - - holder.notificationsItemCard.setOnClickListener((v -> { - Intent intent = new Intent("android.intent.action.MAIN"); - notification.fillIntent(intent); - - d(TAG, "notification with item "+notification.redirectFragmentId+" extras "+(intent.getExtras() == null ? "null" : intent.getExtras().toString())); - - //Log.d(TAG, "Got date "+intent.getLongExtra("timetableDate", 0)); - - if (notification.profileId != -1 && notification.profileId != app.profile.getId() && context instanceof Activity) { - Toast.makeText(app, app.getString(R.string.toast_changing_profile), Toast.LENGTH_LONG).show(); - } - app.sendBroadcast(intent); - })); - - if (!notification.seen) { - holder.notificationsItemText.setBackground(context.getResources().getDrawable(R.drawable.bg_rounded_8dp)); - holder.notificationsItemText.getBackground().setColorFilter(new PorterDuffColorFilter(0x692196f3, PorterDuff.Mode.MULTIPLY)); - } - else { - holder.notificationsItemText.setBackground(null); - } - - } - - @Override - public int getItemCount() { - return notificationList.size(); - } - - class ViewHolder extends RecyclerView.ViewHolder { - - CardView notificationsItemCard; - TextView notificationsItemDate; - TextView notificationsItemText; - TextView notificationsItemTitle; - TextView notificationsItemType; - - ViewHolder(View itemView) { - super(itemView); - notificationsItemCard = itemView.findViewById(R.id.notificationsItemCard); - notificationsItemDate = itemView.findViewById(R.id.notificationsItemDate); - notificationsItemText = itemView.findViewById(R.id.notificationsItemText); - notificationsItemTitle = itemView.findViewById(R.id.notificationsItemTitle); - notificationsItemType = itemView.findViewById(R.id.notificationsItemType); - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsAdapter.kt new file mode 100644 index 00000000..7ae78edd --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsAdapter.kt @@ -0,0 +1,72 @@ +package pl.szczodrzynski.edziennik.ui.modules.notifications + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import android.widget.Toast +import androidx.recyclerview.widget.RecyclerView +import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.data.db.modules.notification.Notification +import pl.szczodrzynski.edziennik.data.db.modules.notification.getNotificationTitle +import pl.szczodrzynski.edziennik.utils.Utils.d +import pl.szczodrzynski.edziennik.utils.models.Date + +class NotificationsAdapter( + private val context: Context +) : RecyclerView.Adapter() { + companion object { + private const val TAG = "NotificationsAdapter" + } + + var items = listOf() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val inflater = LayoutInflater.from(context) + val view = inflater.inflate(R.layout.row_notifications_item, parent, false) + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val app = context.applicationContext as App + + val notification = items[position] + + val date = Date.fromMillis(notification.addedDate).formattedString + val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(context) + + holder.title.text = notification.text + holder.profileDate.text = listOf( + notification.profileName ?: "", + " • ", + date.asColoredSpannable(colorSecondary) + ).concat() + holder.type.text = context.getNotificationTitle(notification.type) + + holder.root.onClick { + val intent = Intent("android.intent.action.MAIN") + notification.fillIntent(intent) + + d(TAG, "notification with item " + notification.viewId + " extras " + if (intent.extras == null) "null" else intent.extras!!.toString()) + + //Log.d(TAG, "Got date "+intent.getLongExtra("timetableDate", 0)); + + if (notification.profileId != -1 && notification.profileId != app.profile.id && context is Activity) { + Toast.makeText(app, app.getString(R.string.toast_changing_profile), Toast.LENGTH_LONG).show() + } + app.sendBroadcast(intent) + } + } + + override fun getItemCount() = items.size + + class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + var root = itemView + var title: TextView = itemView.findViewById(R.id.title) + var profileDate: TextView = itemView.findViewById(R.id.profileDate) + var type: TextView = itemView.findViewById(R.id.type) + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsFragment.java deleted file mode 100644 index 0ed54999..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsFragment.java +++ /dev/null @@ -1,65 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.notifications; - -import android.app.Activity; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.databinding.DataBindingUtil; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.databinding.FragmentNotificationsBinding; -import pl.szczodrzynski.edziennik.utils.Themes; - -public class NotificationsFragment extends Fragment { - - private App app = null; - private Activity activity = null; - private FragmentNotificationsBinding b = null; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - activity = getActivity(); - if (getActivity() == null || getContext() == null) - return null; - app = (App) activity.getApplication(); - getContext().getTheme().applyStyle(Themes.INSTANCE.getAppTheme(), true); - if (app.profile == null) - return inflater.inflate(R.layout.fragment_loading, container, false); - // activity, context and profile is valid - b = DataBindingUtil.inflate(inflater, R.layout.fragment_notifications, container, false); - return b.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (app == null || app.profile == null || activity == null || b == null || !isAdded()) - return; - - RecyclerView recyclerView = b.notificationsView; - recyclerView.setHasFixedSize(true); - recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - - if (app.appConfig.notifications.size() > 0) { - NotificationsAdapter adapter = new NotificationsAdapter(getContext(), app.appConfig.notifications); - recyclerView.setAdapter(adapter); - recyclerView.setVisibility(View.VISIBLE); - LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext()); - //linearLayoutManager.setReverseLayout(true); - //linearLayoutManager.setStackFromEnd(true); - recyclerView.setLayoutManager(linearLayoutManager); - b.notificationsNoData.setVisibility(View.GONE); - } - else { - recyclerView.setVisibility(View.GONE); - b.notificationsNoData.setVisibility(View.VISIBLE); - } - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsFragment.kt new file mode 100644 index 00000000..e63e11cb --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/notifications/NotificationsFragment.kt @@ -0,0 +1,90 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2019-11-22. + */ + +package pl.szczodrzynski.edziennik.ui.modules.notifications + +import android.os.AsyncTask +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.DividerItemDecoration.HORIZONTAL +import androidx.recyclerview.widget.LinearLayoutManager +import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.MainActivity +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.FragmentNotificationsBinding +import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration +import pl.szczodrzynski.edziennik.utils.Themes +import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem + + +class NotificationsFragment : Fragment() { + private lateinit var app: App + private lateinit var activity: MainActivity + private lateinit var b: FragmentNotificationsBinding + + private val adapter by lazy { + NotificationsAdapter(activity) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + activity = (getActivity() as MainActivity?) ?: return null + if (context == null) + return null + app = activity.application as App + context!!.theme.applyStyle(Themes.appTheme, true) + if (app.profile == null) + return inflater.inflate(R.layout.fragment_loading, container, false) + // activity, context and profile is valid + b = FragmentNotificationsBinding.inflate(inflater) + return b.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + // TODO check if app, activity, b can be null + if (app.profile == null || !isAdded) + return + + activity.bottomSheet.prependItems( + BottomSheetPrimaryItem(true) + .withTitle(R.string.menu_remove_notifications) + .withIcon(CommunityMaterial.Icon.cmd_delete_sweep_outline) + .withOnClickListener(View.OnClickListener { + activity.bottomSheet.close() + AsyncTask.execute { app.db.notificationDao().clearAll() } + Toast.makeText(activity, R.string.menu_remove_notifications_success, Toast.LENGTH_SHORT).show() + })) + + app.db.notificationDao() + .getAll() + .observe(this, Observer { notifications -> + if (app.profile == null || !isAdded) return@Observer + + adapter.items = notifications + if (b.notificationsView.adapter == null) { + b.notificationsView.adapter = adapter + b.notificationsView.apply { + setHasFixedSize(true) + layoutManager = LinearLayoutManager(context).apply { + addItemDecoration(SimpleDividerItemDecoration(context)) + } + } + } + adapter.notifyDataSetChanged() + + if (notifications != null && notifications.isNotEmpty()) { + b.notificationsView.visibility = View.VISIBLE + b.notificationsNoData.visibility = View.GONE + } else { + b.notificationsView.visibility = View.GONE + b.notificationsNoData.visibility = View.VISIBLE + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/SimpleDividerItemDecoration.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/SimpleDividerItemDecoration.java new file mode 100644 index 00000000..60350f23 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/SimpleDividerItemDecoration.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2019-11-22. + */ + +package pl.szczodrzynski.edziennik.utils; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +import pl.szczodrzynski.edziennik.R; + +public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration { + private Drawable mDivider; + + public SimpleDividerItemDecoration(Context context) { + mDivider = context.getResources().getDrawable(R.drawable.divider); + } + + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + int left = parent.getPaddingLeft(); + int right = parent.getWidth() - parent.getPaddingRight(); + + int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = parent.getChildAt(i); + + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + + int top = child.getBottom() + params.bottomMargin; + int bottom = top + mDivider.getIntrinsicHeight(); + + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } +} diff --git a/app/src/main/res/drawable/divider.xml b/app/src/main/res/drawable/divider.xml new file mode 100644 index 00000000..a1e368c0 --- /dev/null +++ b/app/src/main/res/drawable/divider.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_no_notifications.xml b/app/src/main/res/drawable/ic_no_notifications.xml new file mode 100644 index 00000000..b94f7e12 --- /dev/null +++ b/app/src/main/res/drawable/ic_no_notifications.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_notifications.xml b/app/src/main/res/layout/fragment_notifications.xml index 96e7cdfd..e63cd2e9 100644 --- a/app/src/main/res/layout/fragment_notifications.xml +++ b/app/src/main/res/layout/fragment_notifications.xml @@ -1,35 +1,29 @@ - + - - + android:layout_height="match_parent" + tools:listitem="@layout/row_notifications_item" + tools:visibility="gone" /> + tools:visibility="visible" /> - + \ No newline at end of file diff --git a/app/src/main/res/layout/row_notifications_item.xml b/app/src/main/res/layout/row_notifications_item.xml index 1e079aab..3ef2f6d8 100644 --- a/app/src/main/res/layout/row_notifications_item.xml +++ b/app/src/main/res/layout/row_notifications_item.xml @@ -1,75 +1,35 @@ + android:orientation="vertical" + android:padding="8dp" + android:background="?selectableItemBackground"> - + android:textAppearance="@style/NavView.TextView.Medium" + tools:text="Dzisiaj 1 to szczęśliwy numerek" /> - + - + - - - - - - - - - - - - - - + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 210529bb..44e889f7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1028,4 +1028,6 @@ (brak nazwy) Więcej opcji Pobieranie komentarzy ocen... + Usuń wszystkie + Wyczyszczono powiadomienia