org.comixwall.pffw.Notifications.java Source code

Java tutorial

Introduction

Here is the source code for org.comixwall.pffw.Notifications.java

Source

/*
 * Copyright (C) 2017-2018 Soner Tari
 *
 * This file is part of PFFW.
 *
 * PFFW 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.
 *
 * PFFW 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 PFFW.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.comixwall.pffw;

import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import static org.comixwall.pffw.MainActivity.controller;
import static org.comixwall.pffw.MainActivity.fragment;
import static org.comixwall.pffw.MainActivity.lastNotificationTimestamp;
import static org.comixwall.pffw.MainActivity.logger;

public class Notifications extends Fragment
        implements RecyclerTouchListener.OnItemClickListener, ControllerTask.ControllerTaskListener {

    private static final List<Notification> mNotificationsList = new ArrayList<>();

    private RecyclerView rvNotifications;

    private static final ArrayList<String> priorities = new ArrayList<String>() {
        {
            add("Critical");
            add("Error");
            add("Warning");
        }
    };

    public static void addNotification(Notification element) {
        // Recent notifications first, hence use id 0
        mNotificationsList.add(0, element);

        // Limit the number of notifications
        int count = mNotificationsList.size();
        if (count > 100) {
            logger.finest(
                    "addNotification reached max notification count, removing oldest notification, id= " + count);
            mNotificationsList.remove(count - 1);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.notifications, container, false);

        rvNotifications = view.findViewById(R.id.recyclerViewNotifications);

        rvNotifications.setLayoutManager(new LinearLayoutManager(getActivity()));
        rvNotifications.setItemAnimator(new DefaultItemAnimator());
        rvNotifications.addItemDecoration(new RecyclerDivider(getActivity(), LinearLayoutManager.VERTICAL));
        rvNotifications.setAdapter(new NotificationRecyclerAdapter(mNotificationsList));
        rvNotifications.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), this));

        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        fragment = this;
    }

    @Override
    public void onItemClick(View view) {

        TextView tvTitle = view.findViewById(R.id.title);
        TextView tvBody = view.findViewById(R.id.body);

        int lines = 10;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            if (tvTitle.getMaxLines() != 1) {
                lines = 1;
            }
        }

        tvTitle.setMaxLines(lines);
        tvBody.setMaxLines(lines);

        List<NotificationDetail> details = new ArrayList<>();

        // Position == view id
        Notification notification = mNotificationsList.get(view.getId());
        try {
            JSONObject jsonArray = new JSONObject(notification.data);

            for (String p : priorities) {
                Iterator<String> modules = jsonArray.keys();
                while (modules.hasNext()) {
                    String module = modules.next();
                    Iterator<String> prios = jsonArray.getJSONObject(module).keys();
                    while (prios.hasNext()) {
                        String prio = prios.next();
                        if (prio.contains(p)) {
                            JSONArray logs = jsonArray.getJSONObject(module).getJSONArray(prio);
                            // There is only one sample log record, at index 0
                            details.add(NotificationDetail.newInstance(module, logs.getJSONObject(0)));
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.warning("onItemClick exception= " + e.toString());
        }

        NotificationDetails.setNotificationDetails(details);

        // TODO: Code reuse, unite with MainActivity onNavigationItemSelected()
        fragment = new NotificationDetails();

        Bundle args = new Bundle();
        args.putString("title", notification.title);
        args.putString("body", notification.body);
        args.putString("datetime", notification.datetime);

        fragment.setArguments(args);

        FragmentManager fm = getActivity().getSupportFragmentManager();
        android.support.v4.app.FragmentTransaction transaction = fm.beginTransaction();
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);

        String fragmentName = fragment.getClass().getSimpleName();
        transaction.addToBackStack(fragmentName);

        transaction.replace(R.id.fragmentContainer, fragment);
        transaction.commit();

        ((MainActivity) getActivity()).createOptionsMenu();
    }

    // ATTENTION: ControllerTask.ControllerTaskListener interface implementation is for deleting token
    // During logout we send delToken command to the firewall using the refresh menu option
    // So all fragments should implement it
    @Override
    public void executePreTask() {
    }

    @Override
    public void preExecute() {
    }

    @Override
    public boolean executeTask() {
        try {
            // Dummy call
            controller.execute("pf", "IsRunning");
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    @Override
    public void postExecute(boolean result) {
    }

    @Override
    public void executeOnCancelled() {
    }

    private void getInfo() {
        ControllerTask.run(this, this);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.menuRefresh) {
            getInfo();
            return true;
        } else if (id == R.id.menuDelete) {
            deleteAllNotifications();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void deleteAllNotifications() {
        mNotificationsList.clear();
        NotificationRecyclerAdapter rvAdapter = (NotificationRecyclerAdapter) rvNotifications.getAdapter();
        rvAdapter.notificationList.clear();
        rvAdapter.notifyDataSetChanged();
        lastNotificationTimestamp = 0;
    }
}

class Notification {
    String title;
    String body;
    String data;
    String datetime;

    static Notification newInstance(JSONObject notificationEntry) {
        Notification notification = new Notification();
        try {
            JSONObject data = new JSONObject(notificationEntry.getString("data"));
            notification.title = data.getString("title");
            notification.body = data.getString("body");
            notification.data = data.getString("data");
            notification.datetime = data.getString("datetime");
        } catch (Exception e) {
            e.printStackTrace();
            logger.warning("Notification newInstance exception= " + e.toString());
        }
        return notification;
    }
}

class NotificationRecyclerAdapter extends RecyclerView.Adapter<NotificationRecyclerAdapter.NotificationViewHolder> {

    public final List<Notification> notificationList = new ArrayList<>();

    class NotificationViewHolder extends RecyclerView.ViewHolder {
        final TextView title;
        final TextView body;
        final TextView datetime;
        final TextView image;

        NotificationViewHolder(View view) {
            super(view);
            title = view.findViewById(R.id.title);
            body = view.findViewById(R.id.body);
            datetime = view.findViewById(R.id.datetime);
            image = view.findViewById(R.id.image);
        }
    }

    NotificationRecyclerAdapter(List<Notification> list) {
        this.notificationList.clear();
        this.notificationList.addAll(list);
    }

    @Override
    public NotificationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.notification, parent, false);

        return new NotificationViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(NotificationViewHolder holder, int position) {
        Notification notification = notificationList.get(position);

        // Use position as id, so we know the notification that the user clicks on
        holder.itemView.setId(position);

        holder.title.setText(notification.title);
        holder.body.setText(notification.body);
        holder.datetime.setText(notification.datetime);

        int image;
        String caption;

        if (notification.title.contains("critical errors")) {
            image = R.drawable.block;
            caption = "C";
        } else if (notification.title.contains("errors")) {
            image = R.drawable.match;
            caption = "E";
        } else {
            image = R.drawable.pass;
            caption = "W";
        }

        holder.image.setBackgroundResource(image);
        holder.image.setText(caption);
    }

    @Override
    public int getItemCount() {
        return notificationList.size();
    }
}