Added bug report
This commit is contained in:
parent
63e3276098
commit
d47aeccd87
53 changed files with 1137 additions and 229 deletions
|
@ -24,7 +24,7 @@ class SongShareDialog : RoundedBottomSheetDialogFragment() {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
val song = arguments!!.getParcelable<Song>("song")!!
|
||||
|
||||
audioFile.text = getString(R.string.currently_listening_to_x_by_x, song.title, song.artistName)
|
||||
audioText.text = getString(R.string.currently_listening_to_x_by_x, song.title, song.artistName)
|
||||
audioFile.setTextColor(ThemeStore.textColorSecondary(context!!))
|
||||
audioText.setTextColor(ThemeStore.textColorSecondary(context!!))
|
||||
title.setTextColor(ThemeStore.textColorPrimary(context!!))
|
||||
|
|
|
@ -26,6 +26,7 @@ import code.name.monkey.retromusic.loaders.ArtistLoader
|
|||
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.ui.activities.base.AbsSlidingMusicPanelActivity
|
||||
import code.name.monkey.retromusic.ui.activities.bugreport.BugReportActivity
|
||||
import code.name.monkey.retromusic.ui.fragments.mainactivity.LibraryFragment
|
||||
import code.name.monkey.retromusic.ui.fragments.mainactivity.folders.FoldersFragment
|
||||
import code.name.monkey.retromusic.ui.fragments.mainactivity.home.BannerHomeFragment
|
||||
|
@ -308,7 +309,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
|
|||
}
|
||||
|
||||
private fun prepareBugReport() {
|
||||
|
||||
startActivity(Intent(this, BugReportActivity::class.java))
|
||||
}
|
||||
|
||||
private fun shareApp() {
|
||||
|
|
|
@ -3,7 +3,6 @@ package code.name.monkey.retromusic.ui.activities.base
|
|||
import android.animation.ArgbEvaluator
|
||||
import android.animation.ValueAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -11,7 +10,6 @@ import android.view.ViewTreeObserver
|
|||
import androidx.annotation.FloatRange
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
|
@ -170,8 +168,6 @@ abstract class AbsSlidingMusicPanelActivity protected constructor() : AbsMusicSe
|
|||
override fun onPanelSlide(panel: View?, slideOffset: Float) {
|
||||
bottomNavigationView.translationY = slideOffset * 400
|
||||
setMiniPlayerAlphaProgress(slideOffset)
|
||||
//if (navigationBarColorAnimator != null) navigationBarColorAnimator.cancel();
|
||||
//super.setNavigationbarColor((int) argbEvaluator.evaluate(slideOffset, navigationbarColor, Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
override fun onPanelStateChanged(panel: View, previousState: PanelState, newState: PanelState) {
|
||||
|
@ -230,7 +226,7 @@ abstract class AbsSlidingMusicPanelActivity protected constructor() : AbsMusicSe
|
|||
NowPlayingScreen.PLAIN -> PlainPlayerFragment()
|
||||
NowPlayingScreen.SIMPLE -> SimplePlayerFragment()
|
||||
NowPlayingScreen.MATERIAL -> MaterialFragment()
|
||||
NowPlayingScreen.COLOR->ColorFragment()
|
||||
NowPlayingScreen.COLOR -> ColorFragment()
|
||||
else -> PlayerFragment()
|
||||
} // must implement AbsPlayerFragment
|
||||
supportFragmentManager.beginTransaction().replace(R.id.player_fragment_container, fragment).commit()
|
||||
|
@ -261,16 +257,17 @@ abstract class AbsSlidingMusicPanelActivity protected constructor() : AbsMusicSe
|
|||
override fun onPaletteColorChanged() {
|
||||
if (panelState == PanelState.EXPANDED) {
|
||||
val paletteColor = playerFragment!!.paletteColor
|
||||
ColorUtil.isColorLight(paletteColor)
|
||||
super.setTaskDescriptionColor(paletteColor)
|
||||
if (currentNowPlayingScreen == NowPlayingScreen.BLUR) {
|
||||
|
||||
val isColorLight = ColorUtil.isColorLight(paletteColor)
|
||||
if (PreferenceUtil.getInstance().adaptiveColor &&
|
||||
(currentNowPlayingScreen == NowPlayingScreen.NORMAL || currentNowPlayingScreen == NowPlayingScreen.FLAT)) {
|
||||
super.setLightNavigationBar(true)
|
||||
super.setLightStatusbar(isColorLight)
|
||||
} else if (currentNowPlayingScreen == NowPlayingScreen.FULL || currentNowPlayingScreen == NowPlayingScreen.CARD ||
|
||||
currentNowPlayingScreen == NowPlayingScreen.BLUR || currentNowPlayingScreen == NowPlayingScreen.BLUR_CARD) {
|
||||
super.setLightStatusbar(false)
|
||||
super.setLightNavigationBar(true)
|
||||
} else {
|
||||
val isTheme = isOneOfTheseThemes && ColorUtil.isColorLight(ThemeStore.primaryColor(this))
|
||||
super.setStatusbarColor(Color.TRANSPARENT)
|
||||
super.setLightStatusbar(isTheme)
|
||||
super.setLightNavigationBar(isTheme)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
package code.name.monkey.retromusic.ui.activities.bugreport
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.MenuItem
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.StringDef
|
||||
import androidx.annotation.StringRes
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.TintHelper
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.misc.DialogAsyncTask
|
||||
import code.name.monkey.retromusic.ui.activities.base.AbsThemeActivity
|
||||
import code.name.monkey.retromusic.ui.activities.bugreport.model.DeviceInfo
|
||||
import code.name.monkey.retromusic.ui.activities.bugreport.model.Report
|
||||
import code.name.monkey.retromusic.ui.activities.bugreport.model.github.ExtraInfo
|
||||
import code.name.monkey.retromusic.ui.activities.bugreport.model.github.GithubLogin
|
||||
import code.name.monkey.retromusic.ui.activities.bugreport.model.github.GithubTarget
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import kotlinx.android.synthetic.main.activity_bug_report.*
|
||||
import kotlinx.android.synthetic.main.bug_report_card_device_info.*
|
||||
import kotlinx.android.synthetic.main.bug_report_card_report.*
|
||||
import org.eclipse.egit.github.core.Issue
|
||||
import org.eclipse.egit.github.core.client.GitHubClient
|
||||
import org.eclipse.egit.github.core.client.RequestException
|
||||
import org.eclipse.egit.github.core.service.IssueService
|
||||
import java.io.IOException
|
||||
|
||||
private const val RESULT_SUCCESS = "RESULT_OK"
|
||||
private const val RESULT_BAD_CREDENTIALS = "RESULT_BAD_CREDENTIALS"
|
||||
private const val RESULT_INVALID_TOKEN = "RESULT_INVALID_TOKEN"
|
||||
private const val RESULT_ISSUES_NOT_ENABLED = "RESULT_ISSUES_NOT_ENABLED"
|
||||
private const val RESULT_UNKNOWN = "RESULT_UNKNOWN"
|
||||
|
||||
@StringDef(RESULT_SUCCESS, RESULT_BAD_CREDENTIALS, RESULT_INVALID_TOKEN, RESULT_ISSUES_NOT_ENABLED, RESULT_UNKNOWN)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
private annotation class Result
|
||||
|
||||
open class BugReportActivity : AbsThemeActivity() {
|
||||
|
||||
private var deviceInfo: DeviceInfo? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_bug_report)
|
||||
|
||||
|
||||
setStatusbarColorAuto()
|
||||
setNavigationbarColorAuto()
|
||||
setTaskDescriptionColorAuto()
|
||||
|
||||
initViews()
|
||||
|
||||
if (TextUtils.isEmpty(title))
|
||||
setTitle(R.string.report_an_issue)
|
||||
|
||||
|
||||
deviceInfo = DeviceInfo(this)
|
||||
airTextDeviceInfo!!.text = deviceInfo!!.toString()
|
||||
}
|
||||
|
||||
private fun initViews() {
|
||||
val accentColor = ThemeStore.accentColor(this)
|
||||
val primaryColor = ThemeStore.primaryColor(this)
|
||||
toolbar!!.setBackgroundColor(primaryColor)
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
TintHelper.setTintAuto(optionUseAccount!!, accentColor, false)
|
||||
optionUseAccount!!.setOnClickListener {
|
||||
inputTitle!!.isEnabled = true
|
||||
inputDescription!!.isEnabled = true
|
||||
inputUsername!!.isEnabled = true
|
||||
inputPassword!!.isEnabled = true
|
||||
|
||||
optionAnonymous!!.isChecked = false
|
||||
sendFab!!.hide(object : FloatingActionButton.OnVisibilityChangedListener() {
|
||||
override fun onHidden(fab: FloatingActionButton?) {
|
||||
super.onHidden(fab)
|
||||
sendFab!!.setImageResource(R.drawable.ic_send_white_24dp)
|
||||
sendFab!!.show()
|
||||
}
|
||||
})
|
||||
}
|
||||
TintHelper.setTintAuto(optionAnonymous!!, accentColor, false)
|
||||
optionAnonymous!!.setOnClickListener {
|
||||
inputTitle!!.isEnabled = false
|
||||
inputDescription!!.isEnabled = false
|
||||
inputUsername!!.isEnabled = false
|
||||
inputPassword!!.isEnabled = false
|
||||
|
||||
optionUseAccount!!.isChecked = false
|
||||
sendFab!!.hide(object : FloatingActionButton.OnVisibilityChangedListener() {
|
||||
override fun onHidden(fab: FloatingActionButton?) {
|
||||
super.onHidden(fab)
|
||||
sendFab!!.setImageResource(R.drawable.ic_open_in_browser_white_24dp)
|
||||
sendFab!!.show()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
inputPassword!!.setOnEditorActionListener { _, actionId, event ->
|
||||
if (actionId == EditorInfo.IME_ACTION_SEND) {
|
||||
reportIssue()
|
||||
return@setOnEditorActionListener true
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
airTextDeviceInfo!!.setOnClickListener { copyDeviceInfoToClipBoard() }
|
||||
|
||||
TintHelper.setTintAuto(sendFab!!, accentColor, true)
|
||||
sendFab!!.setOnClickListener { reportIssue() }
|
||||
|
||||
TintHelper.setTintAuto(inputTitle!!, accentColor, false)
|
||||
TintHelper.setTintAuto(inputDescription!!, accentColor, false)
|
||||
TintHelper.setTintAuto(inputUsername!!, accentColor, false)
|
||||
TintHelper.setTintAuto(inputPassword!!, accentColor, false)
|
||||
}
|
||||
|
||||
private fun reportIssue() {
|
||||
if (optionUseAccount!!.isChecked) {
|
||||
if (!validateInput()) return
|
||||
val username = inputUsername!!.text!!.toString()
|
||||
val password = inputPassword!!.text!!.toString()
|
||||
sendBugReport(GithubLogin(username, password))
|
||||
} else {
|
||||
copyDeviceInfoToClipBoard()
|
||||
|
||||
val i = Intent(Intent.ACTION_VIEW)
|
||||
i.data = Uri.parse(ISSUE_TRACKER_LINK)
|
||||
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
startActivity(i)
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyDeviceInfoToClipBoard() {
|
||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText(getString(R.string.device_info), deviceInfo!!.toMarkdown())
|
||||
clipboard.primaryClip = clip
|
||||
|
||||
Toast.makeText(this@BugReportActivity, R.string.copied_device_info_to_clipboard, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
private fun validateInput(): Boolean {
|
||||
var hasErrors = false
|
||||
|
||||
if (optionUseAccount!!.isChecked) {
|
||||
if (TextUtils.isEmpty(inputUsername!!.text)) {
|
||||
setError(inputLayoutUsername!!, R.string.bug_report_no_username)
|
||||
hasErrors = true
|
||||
} else {
|
||||
removeError(inputLayoutUsername!!)
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(inputPassword!!.text)) {
|
||||
setError(inputLayoutPassword!!, R.string.bug_report_no_password)
|
||||
hasErrors = true
|
||||
} else {
|
||||
removeError(inputLayoutPassword!!)
|
||||
}
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(inputTitle!!.text)) {
|
||||
setError(inputLayoutTitle!!, R.string.bug_report_no_title)
|
||||
hasErrors = true
|
||||
} else {
|
||||
removeError(inputLayoutTitle!!)
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(inputDescription!!.text)) {
|
||||
setError(inputLayoutDescription!!, R.string.bug_report_no_description)
|
||||
hasErrors = true
|
||||
} else {
|
||||
removeError(inputLayoutDescription!!)
|
||||
}
|
||||
|
||||
return !hasErrors
|
||||
}
|
||||
|
||||
private fun setError(editTextLayout: TextInputLayout, @StringRes errorRes: Int) {
|
||||
editTextLayout.error = getString(errorRes)
|
||||
}
|
||||
|
||||
private fun removeError(editTextLayout: TextInputLayout) {
|
||||
editTextLayout.error = null
|
||||
}
|
||||
|
||||
private fun sendBugReport(login: GithubLogin) {
|
||||
if (!validateInput()) return
|
||||
|
||||
val bugTitle = inputTitle!!.text!!.toString()
|
||||
val bugDescription = inputDescription!!.text!!.toString()
|
||||
|
||||
val extraInfo = ExtraInfo()
|
||||
onSaveExtraInfo(extraInfo)
|
||||
|
||||
val report = Report(bugTitle, bugDescription, deviceInfo, extraInfo)
|
||||
val target = GithubTarget("h4h13", "RetroMusicPlayer")
|
||||
|
||||
ReportIssueAsyncTask.report(this, report, target, login)
|
||||
}
|
||||
|
||||
private fun onSaveExtraInfo(extraInfo: ExtraInfo) {}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == android.R.id.home) {
|
||||
onBackPressed()
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private class ReportIssueAsyncTask private constructor(activity: Activity, private val report: Report, private val target: GithubTarget,
|
||||
private val login: GithubLogin) : DialogAsyncTask<Void, Void, String>(activity) {
|
||||
|
||||
override fun createDialog(context: Context): Dialog {
|
||||
return MaterialDialog.Builder(context)
|
||||
.progress(true, 0)
|
||||
.progressIndeterminateStyle(true)
|
||||
.title(R.string.bug_report_uploading)
|
||||
.show()
|
||||
}
|
||||
|
||||
@Result
|
||||
override fun doInBackground(vararg params: Void): String {
|
||||
val client: GitHubClient = if (login.shouldUseApiToken()) {
|
||||
GitHubClient().setOAuth2Token(login.apiToken)
|
||||
} else {
|
||||
GitHubClient().setCredentials(login.username, login.password)
|
||||
}
|
||||
|
||||
val issue = Issue().setTitle(report.title).setBody(report.description)
|
||||
try {
|
||||
IssueService(client).createIssue(target.username, target.repository, issue)
|
||||
return RESULT_SUCCESS
|
||||
} catch (e: RequestException) {
|
||||
return when (e.status) {
|
||||
STATUS_BAD_CREDENTIALS -> {
|
||||
if (login.shouldUseApiToken()) RESULT_INVALID_TOKEN else RESULT_BAD_CREDENTIALS
|
||||
}
|
||||
STATUS_ISSUES_NOT_ENABLED -> RESULT_ISSUES_NOT_ENABLED
|
||||
else -> {
|
||||
e.printStackTrace()
|
||||
RESULT_UNKNOWN
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
return RESULT_UNKNOWN
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onPostExecute(@Result result: String) {
|
||||
super.onPostExecute(result)
|
||||
|
||||
val context = context ?: return
|
||||
|
||||
when (result) {
|
||||
RESULT_SUCCESS -> tryToFinishActivity()
|
||||
RESULT_BAD_CREDENTIALS -> MaterialDialog.Builder(context)
|
||||
.title(R.string.bug_report_failed)
|
||||
.content(R.string.bug_report_failed_wrong_credentials)
|
||||
.positiveText(android.R.string.ok)
|
||||
.show()
|
||||
RESULT_INVALID_TOKEN -> MaterialDialog.Builder(context)
|
||||
.title(R.string.bug_report_failed)
|
||||
.content(R.string.bug_report_failed_invalid_token)
|
||||
.positiveText(android.R.string.ok)
|
||||
.show()
|
||||
RESULT_ISSUES_NOT_ENABLED -> MaterialDialog.Builder(context)
|
||||
.title(R.string.bug_report_failed)
|
||||
.content(R.string.bug_report_failed_issues_not_available)
|
||||
.positiveText(android.R.string.ok)
|
||||
.show()
|
||||
else -> MaterialDialog.Builder(context)
|
||||
.title(R.string.bug_report_failed)
|
||||
.content(R.string.bug_report_failed_unknown)
|
||||
.positiveText(android.R.string.ok)
|
||||
.onPositive { _, _ -> tryToFinishActivity() }
|
||||
.cancelListener { tryToFinishActivity() }
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryToFinishActivity() {
|
||||
val context = context
|
||||
if (context is Activity && !context.isFinishing) {
|
||||
context.finish()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun report(activity: Activity, report: Report, target: GithubTarget, login: GithubLogin) {
|
||||
ReportIssueAsyncTask(activity, report, target, login).execute()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val STATUS_BAD_CREDENTIALS = 401
|
||||
private const val STATUS_ISSUES_NOT_ENABLED = 410
|
||||
private const val ISSUE_TRACKER_LINK = "https://github.com/h4h13/RetroMusicPlayer"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package code.name.monkey.retromusic.ui.activities.bugreport.model;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
|
||||
public class DeviceInfo {
|
||||
private final int versionCode;
|
||||
private final String versionName;
|
||||
private final String buildVersion = Build.VERSION.INCREMENTAL;
|
||||
private final String releaseVersion = Build.VERSION.RELEASE;
|
||||
@IntRange(from = 0)
|
||||
private final int sdkVersion = Build.VERSION.SDK_INT;
|
||||
private final String buildID = Build.DISPLAY;
|
||||
private final String brand = Build.BRAND;
|
||||
private final String manufacturer = Build.MANUFACTURER;
|
||||
private final String device = Build.DEVICE;
|
||||
private final String model = Build.MODEL;
|
||||
private final String product = Build.PRODUCT;
|
||||
private final String hardware = Build.HARDWARE;
|
||||
@SuppressLint("NewApi")
|
||||
@SuppressWarnings("deprecation")
|
||||
private final String[] abis = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
||||
Build.SUPPORTED_ABIS : new String[]{Build.CPU_ABI, Build.CPU_ABI2};
|
||||
@SuppressLint("NewApi")
|
||||
private final String[] abis32Bits = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
||||
Build.SUPPORTED_32_BIT_ABIS : null;
|
||||
@SuppressLint("NewApi")
|
||||
private final String[] abis64Bits = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
||||
Build.SUPPORTED_64_BIT_ABIS : null;
|
||||
|
||||
public DeviceInfo(Context context) {
|
||||
PackageInfo packageInfo;
|
||||
try {
|
||||
packageInfo = context.getPackageManager()
|
||||
.getPackageInfo(context.getPackageName(), 0);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
packageInfo = null;
|
||||
}
|
||||
if (packageInfo != null) {
|
||||
versionCode = packageInfo.versionCode;
|
||||
versionName = packageInfo.versionName;
|
||||
} else {
|
||||
versionCode = -1;
|
||||
versionName = null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toMarkdown() {
|
||||
return "Device info:\n"
|
||||
+ "---\n"
|
||||
+ "<table>\n"
|
||||
+ "<tr><td>App version</td><td>" + versionName + "</td></tr>\n"
|
||||
+ "<tr><td>App version code</td><td>" + versionCode + "</td></tr>\n"
|
||||
+ "<tr><td>Android build version</td><td>" + buildVersion + "</td></tr>\n"
|
||||
+ "<tr><td>Android release version</td><td>" + releaseVersion + "</td></tr>\n"
|
||||
+ "<tr><td>Android SDK version</td><td>" + sdkVersion + "</td></tr>\n"
|
||||
+ "<tr><td>Android build ID</td><td>" + buildID + "</td></tr>\n"
|
||||
+ "<tr><td>Device brand</td><td>" + brand + "</td></tr>\n"
|
||||
+ "<tr><td>Device manufacturer</td><td>" + manufacturer + "</td></tr>\n"
|
||||
+ "<tr><td>Device name</td><td>" + device + "</td></tr>\n"
|
||||
+ "<tr><td>Device model</td><td>" + model + "</td></tr>\n"
|
||||
+ "<tr><td>Device product name</td><td>" + product + "</td></tr>\n"
|
||||
+ "<tr><td>Device hardware name</td><td>" + hardware + "</td></tr>\n"
|
||||
+ "<tr><td>ABIs</td><td>" + Arrays.toString(abis) + "</td></tr>\n"
|
||||
+ "<tr><td>ABIs (32bit)</td><td>" + Arrays.toString(abis32Bits) + "</td></tr>\n"
|
||||
+ "<tr><td>ABIs (64bit)</td><td>" + Arrays.toString(abis64Bits) + "</td></tr>\n"
|
||||
+ "</table>\n";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "App version: " + versionName + "\n"
|
||||
+ "App version code: " + versionCode + "\n"
|
||||
+ "Android build version: " + buildVersion + "\n"
|
||||
+ "Android release version: " + releaseVersion + "\n"
|
||||
+ "Android SDK version: " + sdkVersion + "\n"
|
||||
+ "Android build ID: " + buildID + "\n"
|
||||
+ "Device brand: " + brand + "\n"
|
||||
+ "Device manufacturer: " + manufacturer + "\n"
|
||||
+ "Device name: " + device + "\n"
|
||||
+ "Device model: " + model + "\n"
|
||||
+ "Device product name: " + product + "\n"
|
||||
+ "Device hardware name: " + hardware + "\n"
|
||||
+ "ABIs: " + Arrays.toString(abis) + "\n"
|
||||
+ "ABIs (32bit): " + Arrays.toString(abis32Bits) + "\n"
|
||||
+ "ABIs (64bit): " + Arrays.toString(abis64Bits);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package code.name.monkey.retromusic.ui.activities.bugreport.model;
|
||||
|
||||
|
||||
import code.name.monkey.retromusic.ui.activities.bugreport.model.github.ExtraInfo;
|
||||
|
||||
public class Report {
|
||||
private final String title;
|
||||
|
||||
private final String description;
|
||||
|
||||
private final DeviceInfo deviceInfo;
|
||||
|
||||
private final ExtraInfo extraInfo;
|
||||
|
||||
public Report(String title, String description, DeviceInfo deviceInfo, ExtraInfo extraInfo) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.deviceInfo = deviceInfo;
|
||||
this.extraInfo = extraInfo;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description + "\n\n"
|
||||
+ "-\n\n"
|
||||
+ deviceInfo.toMarkdown() + "\n\n"
|
||||
+ extraInfo.toMarkdown();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package code.name.monkey.retromusic.ui.activities.bugreport.model.github;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ExtraInfo {
|
||||
private final Map<String, String> extraInfo = new LinkedHashMap<>();
|
||||
|
||||
public void put(String key, String value) {
|
||||
extraInfo.put(key, value);
|
||||
}
|
||||
|
||||
public void put(String key, boolean value) {
|
||||
extraInfo.put(key, Boolean.toString(value));
|
||||
}
|
||||
|
||||
public void put(String key, double value) {
|
||||
extraInfo.put(key, Double.toString(value));
|
||||
}
|
||||
|
||||
public void put(String key, float value) {
|
||||
extraInfo.put(key, Float.toString(value));
|
||||
}
|
||||
|
||||
public void put(String key, long value) {
|
||||
extraInfo.put(key, Long.toString(value));
|
||||
}
|
||||
|
||||
public void put(String key, int value) {
|
||||
extraInfo.put(key, Integer.toString(value));
|
||||
}
|
||||
|
||||
public void put(String key, Object value) {
|
||||
extraInfo.put(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public void remove(String key) {
|
||||
extraInfo.remove(key);
|
||||
}
|
||||
|
||||
public String toMarkdown() {
|
||||
if (extraInfo.isEmpty()) return "";
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
output.append("Extra info:\n"
|
||||
+ "---\n"
|
||||
+ "<table>\n");
|
||||
for (String key : extraInfo.keySet()) {
|
||||
output.append("<tr><td>")
|
||||
.append(key)
|
||||
.append("</td><td>")
|
||||
.append(extraInfo.get(key))
|
||||
.append("</td></tr>\n");
|
||||
}
|
||||
output.append("</table>\n");
|
||||
|
||||
return output.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package code.name.monkey.retromusic.ui.activities.bugreport.model.github;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
public class GithubLogin {
|
||||
private final String username;
|
||||
|
||||
private final String password;
|
||||
|
||||
private final String apiToken;
|
||||
|
||||
public GithubLogin(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.apiToken = null;
|
||||
}
|
||||
|
||||
public GithubLogin(String apiToken) {
|
||||
this.username = null;
|
||||
this.password = null;
|
||||
this.apiToken = apiToken;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public boolean shouldUseApiToken() {
|
||||
return TextUtils.isEmpty(username) || TextUtils.isEmpty(password);
|
||||
}
|
||||
|
||||
public String getApiToken() {
|
||||
return apiToken;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package code.name.monkey.retromusic.ui.activities.bugreport.model.github;
|
||||
|
||||
public class GithubTarget {
|
||||
private final String username;
|
||||
|
||||
private final String repository;
|
||||
|
||||
public GithubTarget(String username, String repository) {
|
||||
this.username = username;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getRepository() {
|
||||
return repository;
|
||||
}
|
||||
}
|
|
@ -13,11 +13,7 @@ import android.view.animation.AccelerateInterpolator
|
|||
import android.view.animation.DecelerateInterpolator
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
import code.name.monkey.appthemehelper.util.TintHelper
|
||||
|
@ -27,14 +23,14 @@ import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
|
|||
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
|
||||
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.ui.fragments.VolumeFragment
|
||||
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import kotlinx.android.synthetic.main.fragment_player_playback_controls.*
|
||||
import kotlinx.android.synthetic.main.media_button.*
|
||||
import kotlinx.android.synthetic.main.player_time.*
|
||||
import kotlinx.android.synthetic.main.volume_controls.*
|
||||
import code.name.monkey.retromusic.ui.fragments.VolumeFragment
|
||||
|
||||
|
||||
|
||||
|
||||
class BlurPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
||||
|
@ -65,6 +61,8 @@ class BlurPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
|||
}
|
||||
showBonceAnimation()
|
||||
}
|
||||
val volumeFragment = childFragmentManager.findFragmentById(R.id.volumeFragment) as VolumeFragment
|
||||
volumeFragment.tintWhiteColor()
|
||||
}
|
||||
|
||||
private fun updateSong() {
|
||||
|
@ -108,20 +106,15 @@ class BlurPlaybackControlsFragment : AbsPlayerControlsFragment() {
|
|||
}
|
||||
|
||||
override fun setDark(color: Int) {
|
||||
val colorBg = ATHUtil.resolveColor(activity, android.R.attr.colorBackground)
|
||||
if (ColorUtil.isColorLight(colorBg)) {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(activity, true)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(activity, true)
|
||||
} else {
|
||||
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(activity, false)
|
||||
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(activity, false)
|
||||
}
|
||||
lastPlaybackControlsColor = Color.WHITE
|
||||
lastDisabledPlaybackControlsColor = ContextCompat.getColor(context!!, R.color.md_grey_500)
|
||||
|
||||
if (PreferenceUtil.getInstance().adaptiveColor) {
|
||||
setFabColor(color)
|
||||
} else {
|
||||
setFabColor(ThemeStore.accentColor(context!!))
|
||||
}
|
||||
title.setTextColor(lastPlaybackControlsColor)
|
||||
text.setTextColor(lastDisabledPlaybackControlsColor)
|
||||
|
||||
setFabColor(lastPlaybackControlsColor)
|
||||
songCurrentProgress.setTextColor(lastPlaybackControlsColor)
|
||||
songTotalTime.setTextColor(lastPlaybackControlsColor)
|
||||
|
||||
updateRepeatState()
|
||||
updateShuffleState()
|
||||
|
|
|
@ -40,7 +40,7 @@ class AudioSettings : AbsSettingsFragment() {
|
|||
return ri != null
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle, rootKey: String) {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_audio)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ class ImageSettingFragment : AbsSettingsFragment() {
|
|||
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle, rootKey: String) {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_images)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ class NotificationSettingsFragment : AbsSettingsFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle, rootKey: String) {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_notification)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ class NowPlayingSettingsFragment : AbsSettingsFragment(), SharedPreferences.OnSh
|
|||
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle, rootKey: String) {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_now_playing_screen)
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ class OtherSettingsFragment : AbsSettingsFragment() {
|
|||
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle, rootKey: String) {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_blacklist)
|
||||
addPreferencesFromResource(R.xml.pref_playlists)
|
||||
addPreferencesFromResource(R.xml.pref_advanced)
|
||||
|
|
|
@ -28,7 +28,7 @@ class PersonaizeSettingsFragment : AbsSettingsFragment(), SharedPreferences.OnSh
|
|||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle, rootKey: String) {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_ui)
|
||||
addPreferencesFromResource(R.xml.pref_window)
|
||||
addPreferencesFromResource(R.xml.pref_lockscreen)
|
||||
|
|
|
@ -21,10 +21,7 @@ import com.afollestad.materialdialogs.color.ColorChooserDialog
|
|||
class ThemeSettingsFragment : AbsSettingsFragment() {
|
||||
|
||||
override fun invalidateSettings() {
|
||||
|
||||
val primaryColorPref = findPreference(
|
||||
"primary_color") as ATEColorPreference
|
||||
|
||||
val primaryColorPref = findPreference("primary_color") as ATEColorPreference
|
||||
primaryColorPref.isVisible = PreferenceUtil.getInstance().generalTheme == R.style.Theme_RetroMusic_Color
|
||||
val primaryColor = ThemeStore.primaryColor(activity!!)
|
||||
primaryColorPref.setColor(primaryColor, ColorUtil.darkenColor(primaryColor))
|
||||
|
@ -87,8 +84,7 @@ class ThemeSettingsFragment : AbsSettingsFragment() {
|
|||
true
|
||||
}
|
||||
|
||||
val colorAppShortcuts = findPreference(
|
||||
"should_color_app_shortcuts") as TwoStatePreference
|
||||
val colorAppShortcuts = findPreference("should_color_app_shortcuts") as TwoStatePreference
|
||||
if (!VersionUtils.hasNougatMR()) {
|
||||
colorAppShortcuts.isVisible = false
|
||||
} else {
|
||||
|
@ -102,7 +98,7 @@ class ThemeSettingsFragment : AbsSettingsFragment() {
|
|||
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle, rootKey: String) {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.pref_general)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,6 @@ import android.os.Environment;
|
|||
import android.provider.BaseColumns;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.Settings;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.FileProvider;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
@ -29,6 +26,9 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.FileProvider;
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
|
||||
import code.name.monkey.retromusic.loaders.PlaylistLoader;
|
||||
|
@ -59,20 +59,13 @@ public class MusicUtil {
|
|||
@NonNull
|
||||
public static Intent createShareSongFileIntent(@NonNull final Song song, Context context) {
|
||||
try {
|
||||
|
||||
return new Intent()
|
||||
.setAction(Intent.ACTION_SEND)
|
||||
.putExtra(Intent.EXTRA_STREAM,
|
||||
FileProvider.getUriForFile(context,
|
||||
context.getApplicationContext().getPackageName(),
|
||||
new File(song.getData())))
|
||||
return new Intent().setAction(Intent.ACTION_SEND).putExtra(Intent.EXTRA_STREAM,
|
||||
FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName(), new File(song.getData())))
|
||||
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
.setType("audio/*");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO the path is most likely not like /storage/emulated/0/... but something like /storage/28C7-75B0/...
|
||||
e.printStackTrace();
|
||||
Toast.makeText(context, "Could not share this file, I'm aware of the issue.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(context, "Could not share this file, I'm aware of the issue.", Toast.LENGTH_SHORT).show();
|
||||
return new Intent();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue