Skip to content

Commit

Permalink
Add ReportActivity and ReportInfo
Browse files Browse the repository at this point in the history
This implements the framework to report info to users. This may include reporting failure or result of commands or any exceptions that are raised.

The ReportInfo provides 5 fields:
- userAction: The user action that was being processed for which the report was generated.
- sender: The internal app component that sent the report.
- title: The report title.
- reportString: The markdown text for the report.
- addReportAndDeviceDetails: If set to true, then report and device details will be added to the report.

This should provide the basics parameters for showing a report to the user. The ReportActivity also allows user to copy and share the report.

In future this can also be used to allow users to easily email or post crash reports to github for Termux app crashes instead of going through logcat.
  • Loading branch information
agnostic-apollo committed Mar 23, 2021
1 parent 3491956 commit 9d36e9a
Show file tree
Hide file tree
Showing 15 changed files with 386 additions and 7 deletions.
6 changes: 6 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@
android:label="@string/title_activity_termux_settings"
android:theme="@style/Theme.AppCompat.Light.DarkActionBar" />

<activity
android:name=".app.activities.ReportActivity"
android:theme="@style/Theme.AppCompat.TermuxReportActivity"
android:documentLaunchMode="intoExisting"
/>

<activity
android:name=".filepicker.TermuxFileReceiverActivity"
android:excludeFromRecents="true"
Expand Down
190 changes: 190 additions & 0 deletions app/src/main/java/com/termux/app/activities/ReportActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package com.termux.app.activities;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import com.termux.R;
import com.termux.app.TermuxConstants;
import com.termux.app.utils.MarkdownUtils;
import com.termux.app.utils.ShareUtils;
import com.termux.app.utils.TermuxUtils;
import com.termux.models.ReportInfo;

import org.commonmark.node.FencedCodeBlock;

import io.noties.markwon.Markwon;
import io.noties.markwon.recycler.MarkwonAdapter;
import io.noties.markwon.recycler.SimpleEntry;

public class ReportActivity extends AppCompatActivity {

private static final String ARG_REPORT_INFO = "report_info";

ReportInfo mReportInfo;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_report);

Toolbar toolbar = findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
}

Bundle bundle = null;
Intent intent = getIntent();
if(intent != null)
bundle = intent.getExtras();
else if(savedInstanceState != null)
bundle = savedInstanceState;

updateUI(bundle);

}

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);

if(intent != null)
updateUI(intent.getExtras());
}

private void updateUI(Bundle bundle) {

if (bundle == null) {
finish();
return;
}

mReportInfo = (ReportInfo) bundle.getSerializable(ARG_REPORT_INFO);

if (mReportInfo == null) {
finish();
return;
}


final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
if (mReportInfo.reportTitle != null)
actionBar.setTitle(mReportInfo.reportTitle);
else
actionBar.setTitle(TermuxConstants.TERMUX_APP_NAME + " App Report");
}


RecyclerView recyclerView = findViewById(R.id.recycler_view);

final Markwon markwon = MarkdownUtils.getRecyclerMarkwonBuilder(this);

final MarkwonAdapter adapter = MarkwonAdapter.builderTextViewIsRoot(R.layout.activity_report_adapter_node_default)
.include(FencedCodeBlock.class, SimpleEntry.create(R.layout.activity_report_adapter_node_code_block, R.id.text_view))
.build();

recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);

adapter.setMarkdown(markwon, mReportInfo.reportString + getReportAndDeviceDetailsMarkdownString());
adapter.notifyDataSetChanged();
}



@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);

outState.putSerializable(ARG_REPORT_INFO, mReportInfo);
}

@Override
public boolean onCreateOptionsMenu(final Menu menu) {
final MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_report, menu);
return true;
}

@Override
public void onBackPressed() {
// Remove activity from recents menu on back button press
finishAndRemoveTask();
}

@Override
public boolean onOptionsItemSelected(final MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_item_share_report) {
if (mReportInfo != null)
ShareUtils.shareText(this, getString(R.string.report_text), mReportInfo.reportString);
} else if (id == R.id.menu_item_copy_report) {
if (mReportInfo != null)
ShareUtils.copyTextToClipboard(this, mReportInfo.reportString, null);
}

return false;
}

/**
* Get a markdown {@link String} for {@link #mReportInfo} and device details.
*
* @return Returns the markdown {@link String}.
*/
private String getReportAndDeviceDetailsMarkdownString() {
if(!mReportInfo.addReportAndDeviceDetails) return "";

StringBuilder markdownString = new StringBuilder();

markdownString.append("\n\n### Report And Device Details\n\n");

if (mReportInfo != null) {
markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("User Action", mReportInfo.userAction, "-"));
markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Sender", mReportInfo.sender, "-"));
}

markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Timestamp", TermuxUtils.getCurrentTimeStamp(), "-"));

markdownString.append("\n\n").append(TermuxUtils.getDeviceDetailsMarkdownString(this));

markdownString.append("\n##\n");

return markdownString.toString();
}



public static void startReportActivity(@NonNull final Context context, @NonNull final ReportInfo reportInfo) {
if(context == null) return;
context.startActivity(newInstance(context, reportInfo));
}

public static Intent newInstance(@NonNull final Context context, @NonNull final ReportInfo reportInfo) {
if(context == null) return null;

Intent intent = new Intent(context, ReportActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable(ARG_REPORT_INFO, reportInfo);
intent.putExtras(bundle);

// Note that ReportActivity task has documentLaunchMode="intoExisting" set in AndroidManifest.xml
// which has equivalent behaviour to the following. The following dynamic way doesn't seem to
// work for notification pending intent, i.e separate task isn't created and activity is
// launched in the same task as TermuxActivity.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
return intent;
}

}
26 changes: 26 additions & 0 deletions app/src/main/java/com/termux/models/ReportInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.termux.models;

import java.io.Serializable;

public class ReportInfo implements Serializable {

/** The user action that was being processed for which the report was generated. */
public UserAction userAction;
/** The internal app component that sent the report. */
public String sender;
/** The report title. */
public String reportTitle;
/** The markdown text for the report. */
public String reportString;
/** If set to {@code true}, then report and device details will be added to the report. */
public boolean addReportAndDeviceDetails;

public ReportInfo(UserAction userAction, String sender, String reportTitle, String reportString, boolean addReportAndDeviceDetails) {
this.userAction = userAction;
this.sender = sender;
this.reportTitle = reportTitle;
this.reportString = reportString;
this.addReportAndDeviceDetails = addReportAndDeviceDetails;
}

}
17 changes: 17 additions & 0 deletions app/src/main/java/com/termux/models/UserAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.termux.models;

public enum UserAction {

PLUGIN_EXECUTION_COMMAND("plugin execution command");

private final String name;

UserAction(final String name) {
this.name = name;
}

public String getName() {
return name;
}

}
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/ic_copy.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
</vector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/ic_share.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>
21 changes: 21 additions & 0 deletions app/src/main/res/layout/activity_report.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<include
layout="@layout/toolbar_layout"
android:id="@+id/toolbar_layout"/>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingTop="@dimen/content_padding"
android:paddingBottom="36dip" />

</LinearLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:fillViewport="true"
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:scrollbarStyle="outsideInset">

<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/background_markdown_code_block"
android:fontFamily="monospace"
android:lineSpacingExtra="2dip"
android:paddingLeft="16dip"
android:paddingTop="8dip"
android:paddingRight="16dip"
android:paddingBottom="8dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="12sp"
android:textIsSelectable="true" />

</HorizontalScrollView>
17 changes: 17 additions & 0 deletions app/src/main/res/layout/activity_report_adapter_node_default.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:breakStrategy="simple"
android:hyphenationFrequency="none"
android:lineSpacingExtra="2dip"
android:paddingTop="8dip"
android:paddingBottom="8dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#000"
android:textSize="12sp"
android:textIsSelectable="true" />
22 changes: 22 additions & 0 deletions app/src/main/res/layout/toolbar_layout.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimaryDark"
android:gravity="center_vertical"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:titleTextAppearance="@style/Toolbar.Title">

</androidx.appcompat.widget.Toolbar>

</LinearLayout>
15 changes: 15 additions & 0 deletions app/src/main/res/menu/menu_report.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<item
android:id="@+id/menu_item_share_report"
android:icon="@drawable/ic_share"
android:title="@string/share"
app:showAsAction="never" />
<item
android:id="@+id/menu_item_copy_report"
android:icon="@drawable/ic_copy"
android:title="@string/copy"
app:showAsAction="never" />
</menu>
5 changes: 5 additions & 0 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="background_markdown_code_inline">#1F000000</color>
<color name="background_markdown_code_block">#0F000000</color>
</resources>
10 changes: 10 additions & 0 deletions app/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>

<dimen name="content_padding">8dip</dimen>
<dimen name="content_padding_double">16dip</dimen>
<dimen name="content_padding_half">4dip</dimen>
</resources>
Loading

0 comments on commit 9d36e9a

Please sign in to comment.