mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-03 17:59:51 +02:00
Extend sync diagnose
This commit is contained in:
parent
e69c5a081b
commit
9d93c19de3
6 changed files with 132 additions and 1 deletions
|
@ -85,6 +85,10 @@ class SyncUtil (private val logic: AppLogic) {
|
|||
shouldSyncImportant.or(shouldSyncUnimportant).or(shouldSyncVeryUnimportant)
|
||||
)
|
||||
|
||||
private val lastSyncExceptionInternal = MutableLiveData<Exception?>().apply { postValue(null) }
|
||||
val lastSyncException = lastSyncExceptionInternal.castDown()
|
||||
val isSyncing = liveDataFromFunction (pollInterval = 100) { isSyncingLock.isLocked }
|
||||
|
||||
init {
|
||||
runAsync {
|
||||
wipeCacheIfUpdated()
|
||||
|
@ -113,12 +117,15 @@ class SyncUtil (private val logic: AppLogic) {
|
|||
lastSync.value = logic.timeApi.getCurrentUptimeInMillis()
|
||||
|
||||
SyncInBackgroundWorker.deschedule()
|
||||
lastSyncExceptionInternal.postValue(null)
|
||||
|
||||
// wait 2 to 3 seconds before any next sync (debounce)
|
||||
logic.timeApi.sleep((2 * 1000 + random.nextInt(1000)).toLong())
|
||||
} catch (ex: Exception) {
|
||||
// wait 10 to 15 seconds before retrying
|
||||
|
||||
lastSyncExceptionInternal.postValue(ex)
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.w(LOG_TAG, "sync failed", ex)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* TimeLimit Copyright <C> 2019 Jonas Lochmann
|
||||
*
|
||||
* This program 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 version 3 of the License.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.timelimit.android.ui.diagnose
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import io.timelimit.android.R
|
||||
import io.timelimit.android.extensions.showSafe
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
|
||||
class DiagnoseExceptionDialogFragment: DialogFragment() {
|
||||
companion object {
|
||||
private const val DIALOG_TAG = "DiagnoseExceptionDialogFragment"
|
||||
private const val EXCEPTION = "ex"
|
||||
|
||||
fun newInstance(exception: Exception) = DiagnoseExceptionDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable(EXCEPTION, exception)
|
||||
}
|
||||
}
|
||||
|
||||
fun getStackTraceString(tr: Throwable): String = StringWriter().let { sw ->
|
||||
PrintWriter(sw).let { pw ->
|
||||
tr.printStackTrace(pw)
|
||||
pw.flush()
|
||||
}
|
||||
|
||||
sw.toString()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val message = getStackTraceString(arguments!!.getSerializable(EXCEPTION) as Exception)
|
||||
val clipboard = context!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
|
||||
return AlertDialog.Builder(context!!, theme)
|
||||
.setMessage(message)
|
||||
.setNeutralButton(R.string.diagnose_sync_copy_to_clipboard) { _, _ ->
|
||||
clipboard.primaryClip = ClipData.newPlainText("TimeLimit", message)
|
||||
|
||||
Toast.makeText(context, R.string.diagnose_sync_copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
.setPositiveButton(R.string.generic_ok, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
fun show(fragmentManager: FragmentManager) = showSafe(fragmentManager, DIALOG_TAG)
|
||||
}
|
|
@ -28,6 +28,8 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import io.timelimit.android.R
|
||||
import io.timelimit.android.async.Threads
|
||||
import io.timelimit.android.databinding.DiagnoseSyncFragmentBinding
|
||||
import io.timelimit.android.livedata.map
|
||||
import io.timelimit.android.livedata.switchMap
|
||||
import io.timelimit.android.logic.DefaultAppLogic
|
||||
import io.timelimit.android.sync.actions.apply.UploadActionsUtil
|
||||
|
||||
|
@ -36,6 +38,7 @@ class DiagnoseSyncFragment : Fragment() {
|
|||
val binding = DiagnoseSyncFragmentBinding.inflate(inflater, container, false)
|
||||
val logic = DefaultAppLogic.with(context!!)
|
||||
val adapter = PendingSyncActionAdapter()
|
||||
val sync = logic.syncUtil
|
||||
|
||||
binding.recycler.layoutManager = LinearLayoutManager(context!!)
|
||||
binding.recycler.adapter = adapter
|
||||
|
@ -56,11 +59,31 @@ class DiagnoseSyncFragment : Fragment() {
|
|||
}
|
||||
|
||||
binding.requestSyncBtn.setOnClickListener {
|
||||
logic.syncUtil.requestImportantSync(true)
|
||||
sync.requestImportantSync(true)
|
||||
|
||||
Toast.makeText(context!!, R.string.diagnose_sync_btn_request_sync_toast, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
sync.isSyncing.switchMap { a ->
|
||||
sync.lastSyncException.map { b -> a to b }
|
||||
}.observe(this, Observer { (isSyncing, lastSyncException) ->
|
||||
binding.hadSyncException = lastSyncException != null
|
||||
|
||||
if (isSyncing) {
|
||||
binding.syncStatusText = getString(R.string.diagnose_sync_status_syncing)
|
||||
} else if (lastSyncException != null) {
|
||||
binding.syncStatusText = getString(R.string.diagnose_sync_status_had_error)
|
||||
} else {
|
||||
binding.syncStatusText = getString(R.string.diagnose_sync_status_idle)
|
||||
}
|
||||
})
|
||||
|
||||
binding.showExceptionBtn.setOnClickListener {
|
||||
sync.lastSyncException.value?.let { ex ->
|
||||
DiagnoseExceptionDialogFragment.newInstance(ex).show(fragmentManager!!)
|
||||
}
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,14 @@
|
|||
name="isListEmpty"
|
||||
type="Boolean" />
|
||||
|
||||
<variable
|
||||
name="syncStatusText"
|
||||
type="String" />
|
||||
|
||||
<variable
|
||||
name="hadSyncException"
|
||||
type="boolean" />
|
||||
|
||||
<import type="android.view.View" />
|
||||
</data>
|
||||
|
||||
|
@ -50,6 +58,22 @@
|
|||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:gravity="center_horizontal"
|
||||
tools:text="@string/diagnose_sync_status_idle"
|
||||
android:padding="8dp"
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:text="@{syncStatusText}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Button
|
||||
android:visibility="@{hadSyncException ? View.VISIBLE : View.GONE}"
|
||||
android:id="@+id/show_exception_btn"
|
||||
android:text="@string/diagnose_sync_btn_show_exception"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/clear_cache_btn"
|
||||
android:text="@string/diagnose_sync_btn_clear_cache"
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
<string name="diagnose_sync_btn_clear_cache_toast">Cache geleert</string>
|
||||
<string name="diagnose_sync_btn_request_sync">Synchronisation anfordern</string>
|
||||
<string name="diagnose_sync_btn_request_sync_toast">Synchronisation wurde angefordert</string>
|
||||
<string name="diagnose_sync_btn_show_exception">Fehlerdetails anzeigen</string>
|
||||
<string name="diagnose_sync_status_idle">Es läuft gerade keine Synchronisation</string>
|
||||
<string name="diagnose_sync_status_syncing">Es wird jetzt synchronisiert</string>
|
||||
<string name="diagnose_sync_status_had_error">Es trat ein Fehler beim Synchronisieren auf</string>
|
||||
|
||||
<string name="diagnose_fga_title">Erkennung der aktiven App</string>
|
||||
<string name="diagnose_fga_query_range">Abfragezeitraum</string>
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
<string name="diagnose_sync_btn_clear_cache_toast">Cache cleared</string>
|
||||
<string name="diagnose_sync_btn_request_sync">Request sync</string>
|
||||
<string name="diagnose_sync_btn_request_sync_toast">sync was requested</string>
|
||||
<string name="diagnose_sync_btn_show_exception">Show exception details</string>
|
||||
<string name="diagnose_sync_status_idle">Idle</string>
|
||||
<string name="diagnose_sync_status_syncing">Syncing now</string>
|
||||
<string name="diagnose_sync_status_had_error">Idle, exception occurred</string>
|
||||
|
||||
<string name="diagnose_fga_title">Foreground-App-Detection</string>
|
||||
<string name="diagnose_fga_query_range">Requested time range</string>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue