mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-06-12 13:17:42 +02:00
package refactor
This commit is contained in:
@ -4,13 +4,12 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import me.rhunk.snapenhance.action.AbstractAction
|
||||
import me.rhunk.snapenhance.core.BuildConfig
|
||||
import me.rhunk.snapenhance.ui.map.MapActivity
|
||||
|
||||
class OpenMap: AbstractAction("action.open_map") {
|
||||
override fun run() {
|
||||
context.runOnUiThread {
|
||||
val mapActivityIntent = Intent()
|
||||
mapActivityIntent.setClassName(BuildConfig.APPLICATION_ID, MapActivity::class.java.name)
|
||||
mapActivityIntent.setClassName(BuildConfig.APPLICATION_ID, "me.rhunk.snapenhance.ui.MapActivity")
|
||||
mapActivityIntent.putExtra("location", Bundle().apply {
|
||||
putDouble("latitude", context.config.spoof.location.latitude.get().toDouble())
|
||||
putDouble("longitude", context.config.spoof.location.longitude.get().toDouble())
|
||||
|
@ -6,7 +6,7 @@ import android.database.sqlite.SQLiteDatabase
|
||||
import me.rhunk.snapenhance.download.data.DownloadMetadata
|
||||
import me.rhunk.snapenhance.download.data.DownloadObject
|
||||
import me.rhunk.snapenhance.download.data.DownloadStage
|
||||
import me.rhunk.snapenhance.ui.download.MediaFilter
|
||||
import me.rhunk.snapenhance.download.data.MediaFilter
|
||||
import me.rhunk.snapenhance.util.SQLiteDatabaseHelper
|
||||
import me.rhunk.snapenhance.util.getIntOrNull
|
||||
import me.rhunk.snapenhance.util.getStringOrNull
|
||||
|
@ -1,4 +1,4 @@
|
||||
package me.rhunk.snapenhance.ui.download
|
||||
package me.rhunk.snapenhance.download.data
|
||||
|
||||
enum class MediaFilter(
|
||||
val key: String,
|
@ -32,7 +32,7 @@ import me.rhunk.snapenhance.hook.HookAdapter
|
||||
import me.rhunk.snapenhance.hook.HookStage
|
||||
import me.rhunk.snapenhance.hook.Hooker
|
||||
import me.rhunk.snapenhance.ui.ViewAppearanceHelper
|
||||
import me.rhunk.snapenhance.ui.download.MediaFilter
|
||||
import me.rhunk.snapenhance.download.data.MediaFilter
|
||||
import me.rhunk.snapenhance.util.download.RemoteMediaResolver
|
||||
import me.rhunk.snapenhance.util.getObjectField
|
||||
import me.rhunk.snapenhance.util.protobuf.ProtoReader
|
||||
|
@ -1,104 +0,0 @@
|
||||
package me.rhunk.snapenhance.ui.download
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.ImageButton
|
||||
import android.widget.ListView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import me.rhunk.snapenhance.SharedContext
|
||||
import me.rhunk.snapenhance.bridge.types.BridgeFileType
|
||||
import me.rhunk.snapenhance.core.R
|
||||
import java.io.File
|
||||
|
||||
class ActionListAdapter(
|
||||
private val activity: DownloadManagerActivity,
|
||||
private val layoutId: Int,
|
||||
private val actions: Array<Pair<String, () -> Unit>>
|
||||
) : ArrayAdapter<Pair<String, () -> Unit>>(activity, layoutId, actions) {
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val view = convertView ?: activity.layoutInflater.inflate(layoutId, parent, false)
|
||||
val action = actions[position]
|
||||
view.isClickable = true
|
||||
|
||||
view.findViewById<TextView>(R.id.feature_text).text = action.first
|
||||
view.setOnClickListener {
|
||||
action.second()
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
}
|
||||
|
||||
class DebugSettingsLayoutInflater(
|
||||
private val activity: DownloadManagerActivity
|
||||
) {
|
||||
private fun confirmAction(title: String, message: String, action: () -> Unit) {
|
||||
activity.runOnUiThread {
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(SharedContext.translation["button.positive"]) { _, _ ->
|
||||
action()
|
||||
}
|
||||
.setNegativeButton(SharedContext.translation["button.negative"]) { _, _ -> }
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSuccessToast() {
|
||||
Toast.makeText(activity, "Success", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
fun inflate(parent: ViewGroup) {
|
||||
val debugSettingsLayout = activity.layoutInflater.inflate(R.layout.debug_settings_page, parent, false)
|
||||
|
||||
val debugSettingsTranslation = activity.translation.getCategory("debug_settings_page")
|
||||
|
||||
debugSettingsLayout.findViewById<ImageButton>(R.id.back_button).setOnClickListener {
|
||||
parent.removeView(debugSettingsLayout)
|
||||
}
|
||||
|
||||
debugSettingsLayout.findViewById<TextView>(R.id.title).text = activity.translation["debug_settings"]
|
||||
|
||||
debugSettingsLayout.findViewById<ListView>(R.id.setting_page_list).apply {
|
||||
adapter = ActionListAdapter(activity, R.layout.debug_setting_item, mutableListOf<Pair<String, () -> Unit>>().apply {
|
||||
add(debugSettingsTranslation["clear_cache_title"] to {
|
||||
context.cacheDir.listFiles()?.forEach {
|
||||
it.deleteRecursively()
|
||||
}
|
||||
showSuccessToast()
|
||||
})
|
||||
|
||||
BridgeFileType.values().forEach { fileType ->
|
||||
val actionName = debugSettingsTranslation.format("clear_file_title", "file_name" to fileType.displayName)
|
||||
add(actionName to {
|
||||
confirmAction(actionName, debugSettingsTranslation.format("clear_file_confirmation", "file_name" to fileType.displayName)) {
|
||||
fileType.resolve(context).deleteRecursively()
|
||||
showSuccessToast()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
add(debugSettingsTranslation["reset_all_title"] to {
|
||||
confirmAction(debugSettingsTranslation["reset_all_title"], debugSettingsTranslation["reset_all_confirmation"]) {
|
||||
arrayOf(context.cacheDir, context.filesDir, File(context.dataDir, "databases"), File(context.dataDir, "shared_prefs")).forEach {
|
||||
it.listFiles()?.forEach { file ->
|
||||
file.deleteRecursively()
|
||||
}
|
||||
}
|
||||
showSuccessToast()
|
||||
}
|
||||
})
|
||||
}.toTypedArray())
|
||||
}
|
||||
|
||||
activity.registerBackCallback {
|
||||
parent.removeView(debugSettingsLayout)
|
||||
}
|
||||
|
||||
parent.addView(debugSettingsLayout)
|
||||
}
|
||||
}
|
@ -1,242 +0,0 @@
|
||||
package me.rhunk.snapenhance.ui.download
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.Adapter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import me.rhunk.snapenhance.Logger
|
||||
import me.rhunk.snapenhance.SharedContext
|
||||
import me.rhunk.snapenhance.core.R
|
||||
import me.rhunk.snapenhance.data.FileType
|
||||
import me.rhunk.snapenhance.download.data.DownloadObject
|
||||
import me.rhunk.snapenhance.download.data.DownloadStage
|
||||
import me.rhunk.snapenhance.util.snap.PreviewUtils
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.net.URL
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
class DownloadListAdapter(
|
||||
private val activity: DownloadManagerActivity,
|
||||
private val downloadList: MutableList<DownloadObject>
|
||||
): Adapter<DownloadListAdapter.ViewHolder>() {
|
||||
private val coroutineScope = CoroutineScope(Dispatchers.IO)
|
||||
private val previewJobs = mutableMapOf<Int, Job>()
|
||||
|
||||
inner class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
|
||||
val bitmojiIcon: ImageView = view.findViewById(R.id.bitmoji_icon)
|
||||
val title: TextView = view.findViewById(R.id.item_title)
|
||||
val subtitle: TextView = view.findViewById(R.id.item_subtitle)
|
||||
val status: TextView = view.findViewById(R.id.item_status)
|
||||
val actionButton: Button = view.findViewById(R.id.item_action_button)
|
||||
val radius by lazy {
|
||||
view.context.resources.getDimensionPixelSize(R.dimen.download_manager_item_preview_radius)
|
||||
}
|
||||
val viewWidth by lazy {
|
||||
view.resources.displayMetrics.widthPixels
|
||||
}
|
||||
val viewHeight by lazy {
|
||||
view.layoutParams.height
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.download_manager_item, parent, false))
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return downloadList.size
|
||||
}
|
||||
|
||||
@SuppressLint("Recycle")
|
||||
private suspend fun handlePreview(download: DownloadObject, holder: ViewHolder) {
|
||||
download.outputFile?.let {
|
||||
val uri = Uri.parse(it)
|
||||
runCatching {
|
||||
if (uri.scheme == "content") {
|
||||
val fileType = activity.contentResolver.openInputStream(uri)!!.use { stream ->
|
||||
FileType.fromInputStream(stream)
|
||||
}
|
||||
fileType to activity.contentResolver.openInputStream(uri)
|
||||
} else {
|
||||
FileType.fromFile(File(it)) to FileInputStream(it)
|
||||
}
|
||||
}.getOrNull()
|
||||
}?.also { (fileType, assetStream) ->
|
||||
val previewBitmap = assetStream?.use { stream ->
|
||||
//don't preview files larger than 30MB
|
||||
if (stream.available() > 30 * 1024 * 1024) return@also
|
||||
|
||||
val tempFile = File.createTempFile("preview", ".${fileType.fileExtension}")
|
||||
tempFile.outputStream().use { output ->
|
||||
stream.copyTo(output)
|
||||
}
|
||||
runCatching {
|
||||
PreviewUtils.createPreviewFromFile(tempFile)?.let { preview ->
|
||||
val offsetY = (preview.height / 2 - holder.viewHeight / 2).coerceAtLeast(0)
|
||||
|
||||
Bitmap.createScaledBitmap(
|
||||
Bitmap.createBitmap(
|
||||
preview, 0, offsetY,
|
||||
preview.width.coerceAtMost(holder.viewWidth),
|
||||
preview.height.coerceAtMost(holder.viewHeight)
|
||||
),
|
||||
holder.viewWidth,
|
||||
holder.viewHeight,
|
||||
false
|
||||
)
|
||||
}
|
||||
}.onFailure {
|
||||
Logger.error("failed to create preview $fileType", it)
|
||||
}.also {
|
||||
tempFile.delete()
|
||||
}.getOrNull()
|
||||
} ?: return@also
|
||||
|
||||
if (coroutineContext.job.isCancelled) return@also
|
||||
Handler(holder.view.context.mainLooper).post {
|
||||
holder.view.background = RoundedBitmapDrawableFactory.create(
|
||||
holder.view.context.resources,
|
||||
previewBitmap
|
||||
).also {
|
||||
it.cornerRadius = holder.radius.toFloat()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateViewHolder(download: DownloadObject, holder: ViewHolder) {
|
||||
holder.status.text = download.downloadStage.toString()
|
||||
holder.view.background = holder.view.context.getDrawable(R.drawable.download_manager_item_background)
|
||||
|
||||
coroutineScope.launch {
|
||||
withTimeout(2000) {
|
||||
handlePreview(download, holder)
|
||||
}
|
||||
}
|
||||
|
||||
val isSaved = download.downloadStage == DownloadStage.SAVED
|
||||
//if the download is in progress, the user can cancel it
|
||||
val canInteract = if (download.job != null) !download.downloadStage.isFinalStage || isSaved
|
||||
else isSaved
|
||||
|
||||
holder.status.visibility = if (isSaved) View.GONE else View.VISIBLE
|
||||
|
||||
with(holder.actionButton) {
|
||||
isEnabled = canInteract
|
||||
alpha = if (canInteract) 1f else 0.5f
|
||||
background = context.getDrawable(if (isSaved) R.drawable.action_button_success else R.drawable.action_button_cancel)
|
||||
setTextColor(context.getColor(if (isSaved) R.color.successColor else R.color.actionBarColor))
|
||||
text = if (isSaved)
|
||||
SharedContext.translation["button.open"]
|
||||
else
|
||||
SharedContext.translation["button.cancel"]
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val pendingDownload = downloadList[position]
|
||||
|
||||
pendingDownload.changeListener = { _, _ ->
|
||||
Handler(holder.view.context.mainLooper).post {
|
||||
updateViewHolder(pendingDownload, holder)
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
|
||||
// holder.bitmojiIcon.setImageResource(R.drawable.bitmoji_blank)
|
||||
|
||||
pendingDownload.metadata.iconUrl?.let { url ->
|
||||
thread(start = true) {
|
||||
runCatching {
|
||||
val iconBitmap = URL(url).openStream().use {
|
||||
BitmapFactory.decodeStream(it)
|
||||
}
|
||||
Handler(holder.view.context.mainLooper).post {
|
||||
holder.bitmojiIcon.setImageBitmap(iconBitmap)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
holder.title.visibility = View.GONE
|
||||
holder.subtitle.visibility = View.GONE
|
||||
|
||||
pendingDownload.metadata.mediaDisplayType?.let {
|
||||
holder.title.text = it
|
||||
holder.title.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
pendingDownload.metadata.mediaDisplaySource?.let {
|
||||
holder.subtitle.text = it
|
||||
holder.subtitle.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
holder.actionButton.setOnClickListener {
|
||||
if (pendingDownload.downloadStage != DownloadStage.SAVED) {
|
||||
pendingDownload.cancel()
|
||||
pendingDownload.downloadStage = DownloadStage.CANCELLED
|
||||
updateViewHolder(pendingDownload, holder)
|
||||
notifyItemChanged(position);
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
pendingDownload.outputFile?.let {
|
||||
fun showFileNotFound() {
|
||||
Toast.makeText(holder.view.context, SharedContext.translation["download_manager_activity.file_not_found_toast"], Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
val uri = Uri.parse(it)
|
||||
val fileType = runCatching {
|
||||
if (uri.scheme == "content") {
|
||||
activity.contentResolver.openInputStream(uri)?.use { input ->
|
||||
FileType.fromInputStream(input)
|
||||
} ?: run {
|
||||
showFileNotFound()
|
||||
return@setOnClickListener
|
||||
}
|
||||
} else {
|
||||
val file = File(it)
|
||||
if (!file.exists()) {
|
||||
showFileNotFound()
|
||||
return@setOnClickListener
|
||||
}
|
||||
FileType.fromFile(file)
|
||||
}
|
||||
}.onFailure { exception ->
|
||||
Logger.error("Failed to open file", exception)
|
||||
}.getOrDefault(FileType.UNKNOWN)
|
||||
if (fileType == FileType.UNKNOWN) {
|
||||
showFileNotFound()
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
intent.setDataAndType(uri, fileType.mimeType)
|
||||
holder.view.context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
updateViewHolder(pendingDownload, holder)
|
||||
}
|
||||
}
|
@ -1,214 +0,0 @@
|
||||
package me.rhunk.snapenhance.ui.download
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.PowerManager
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.ImageButton
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import me.rhunk.snapenhance.SharedContext
|
||||
import me.rhunk.snapenhance.bridge.wrapper.LocaleWrapper
|
||||
import me.rhunk.snapenhance.core.BuildConfig
|
||||
import me.rhunk.snapenhance.core.R
|
||||
import me.rhunk.snapenhance.download.data.DownloadObject
|
||||
|
||||
class DownloadManagerActivity : Activity() {
|
||||
lateinit var translation: LocaleWrapper
|
||||
|
||||
private val backCallbacks = mutableListOf<() -> Unit>()
|
||||
private val fetchedDownloadTasks = mutableListOf<DownloadObject>()
|
||||
private var listFilter = MediaFilter.NONE
|
||||
|
||||
private val preferences by lazy {
|
||||
getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
private fun updateNoDownloadText() {
|
||||
findViewById<TextView>(R.id.no_download_title).let {
|
||||
it.text = translation["no_downloads"]
|
||||
it.visibility = if (fetchedDownloadTasks.isEmpty()) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun updateListContent() {
|
||||
fetchedDownloadTasks.clear()
|
||||
fetchedDownloadTasks.addAll(SharedContext.downloadTaskManager.queryFirstTasks(filter = listFilter).values)
|
||||
|
||||
with(findViewById<RecyclerView>(R.id.download_list)) {
|
||||
adapter?.notifyDataSetChanged()
|
||||
scrollToPosition(0)
|
||||
}
|
||||
updateNoDownloadText()
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onBackPressed() {
|
||||
backCallbacks.lastOrNull()?.let {
|
||||
it()
|
||||
backCallbacks.removeLast()
|
||||
} ?: super.onBackPressed()
|
||||
}
|
||||
|
||||
fun registerBackCallback(callback: () -> Unit) {
|
||||
backCallbacks.add(callback)
|
||||
}
|
||||
|
||||
@SuppressLint("BatteryLife", "NotifyDataSetChanged", "SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
SharedContext.ensureInitialized(this)
|
||||
translation = SharedContext.translation.getCategory("download_manager_activity")
|
||||
|
||||
setContentView(R.layout.download_manager_activity)
|
||||
|
||||
findViewById<TextView>(R.id.title).text = resources.getString(R.string.app_name) + " " + BuildConfig.VERSION_NAME
|
||||
|
||||
findViewById<ImageButton>(R.id.debug_settings_button).setOnClickListener {
|
||||
DebugSettingsLayoutInflater(this).inflate(findViewById(android.R.id.content))
|
||||
}
|
||||
|
||||
with(findViewById<RecyclerView>(R.id.download_list)) {
|
||||
layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this@DownloadManagerActivity)
|
||||
|
||||
adapter = DownloadListAdapter(this@DownloadManagerActivity, fetchedDownloadTasks).apply {
|
||||
registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||
updateNoDownloadText()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
|
||||
override fun getMovementFlags(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder
|
||||
): Int {
|
||||
val download = fetchedDownloadTasks[viewHolder.absoluteAdapterPosition]
|
||||
return if (download.isJobActive()) {
|
||||
0
|
||||
} else {
|
||||
super.getMovementFlags(recyclerView, viewHolder)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||
fetchedDownloadTasks.removeAt(viewHolder.absoluteAdapterPosition).let {
|
||||
SharedContext.downloadTaskManager.removeTask(it)
|
||||
}
|
||||
adapter?.notifyItemRemoved(viewHolder.absoluteAdapterPosition)
|
||||
}
|
||||
}).attachToRecyclerView(this)
|
||||
|
||||
var isLoading = false
|
||||
|
||||
addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
val layoutManager = recyclerView.layoutManager as androidx.recyclerview.widget.LinearLayoutManager
|
||||
val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
|
||||
|
||||
if (lastVisibleItemPosition == RecyclerView.NO_POSITION) {
|
||||
return
|
||||
}
|
||||
|
||||
if (lastVisibleItemPosition == fetchedDownloadTasks.size - 1 && !isLoading) {
|
||||
isLoading = true
|
||||
|
||||
SharedContext.downloadTaskManager.queryTasks(fetchedDownloadTasks.last().downloadId, filter = listFilter).forEach {
|
||||
fetchedDownloadTasks.add(it.value)
|
||||
adapter?.notifyItemInserted(fetchedDownloadTasks.size - 1)
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
arrayOf(
|
||||
Pair(R.id.all_category, MediaFilter.NONE),
|
||||
Pair(R.id.pending_category, MediaFilter.PENDING),
|
||||
Pair(R.id.snap_category, MediaFilter.CHAT_MEDIA),
|
||||
Pair(R.id.story_category, MediaFilter.STORY),
|
||||
Pair(R.id.spotlight_category, MediaFilter.SPOTLIGHT)
|
||||
).let { categoryPairs ->
|
||||
categoryPairs.forEach { pair ->
|
||||
this@DownloadManagerActivity.findViewById<TextView>(pair.first).apply {
|
||||
text = translation["category.${resources.getResourceEntryName(pair.first)}"]
|
||||
}.setOnClickListener { view ->
|
||||
listFilter = pair.second
|
||||
updateListContent()
|
||||
categoryPairs.map { this@DownloadManagerActivity.findViewById<TextView>(it.first) }.forEach {
|
||||
it.setTextColor(getColor(R.color.primaryText))
|
||||
}
|
||||
(view as TextView).setTextColor(getColor(R.color.focusedCategoryColor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this@DownloadManagerActivity.findViewById<Button>(R.id.remove_all_button).also {
|
||||
it.text = translation["remove_all"]
|
||||
}.setOnClickListener {
|
||||
with(AlertDialog.Builder(this@DownloadManagerActivity)) {
|
||||
setTitle(translation["remove_all_title"])
|
||||
setMessage(translation["remove_all_text"])
|
||||
setPositiveButton(SharedContext.translation["button.positive"]) { _, _ ->
|
||||
SharedContext.downloadTaskManager.removeAllTasks()
|
||||
fetchedDownloadTasks.removeIf {
|
||||
if (it.isJobActive()) it.cancel()
|
||||
true
|
||||
}
|
||||
adapter?.notifyDataSetChanged()
|
||||
updateNoDownloadText()
|
||||
}
|
||||
setNegativeButton(SharedContext.translation["button.negative"]) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateListContent()
|
||||
|
||||
if (!preferences.getBoolean("ask_battery_optimisations", true) ||
|
||||
!(getSystemService(Context.POWER_SERVICE) as PowerManager).isIgnoringBatteryOptimizations(packageName)) return
|
||||
|
||||
with(Intent()) {
|
||||
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
|
||||
data = Uri.parse("package:$packageName")
|
||||
startActivityForResult(this, 1)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == 1) {
|
||||
preferences.edit().putBoolean("ask_battery_optimisations", false).apply()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
updateListContent()
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
package me.rhunk.snapenhance.ui.map
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.MotionEvent
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import me.rhunk.snapenhance.core.R
|
||||
import org.osmdroid.config.Configuration
|
||||
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
|
||||
import org.osmdroid.util.GeoPoint
|
||||
import org.osmdroid.views.MapView
|
||||
import org.osmdroid.views.Projection
|
||||
import org.osmdroid.views.overlay.Marker
|
||||
import org.osmdroid.views.overlay.Overlay
|
||||
|
||||
|
||||
class MapActivity : Activity() {
|
||||
|
||||
private lateinit var mapView: MapView
|
||||
|
||||
@SuppressLint("MissingInflatedId", "ResourceType")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val contextBundle = intent.extras?.getBundle("location") ?: return
|
||||
val locationLatitude = contextBundle.getDouble("latitude")
|
||||
val locationLongitude = contextBundle.getDouble("longitude")
|
||||
|
||||
Configuration.getInstance().load(applicationContext, getSharedPreferences("osmdroid", Context.MODE_PRIVATE))
|
||||
|
||||
setContentView(R.layout.map)
|
||||
|
||||
mapView = findViewById(R.id.mapView)
|
||||
mapView.setMultiTouchControls(true);
|
||||
mapView.setTileSource(TileSourceFactory.MAPNIK)
|
||||
|
||||
val startPoint = GeoPoint(locationLatitude, locationLongitude)
|
||||
mapView.controller.setZoom(10.0)
|
||||
mapView.controller.setCenter(startPoint)
|
||||
|
||||
val marker = Marker(mapView)
|
||||
marker.isDraggable = true
|
||||
marker.position = startPoint
|
||||
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
|
||||
|
||||
mapView.overlays.add(object: Overlay() {
|
||||
override fun onSingleTapConfirmed(e: MotionEvent?, mapView: MapView?): Boolean {
|
||||
val proj: Projection = mapView!!.projection
|
||||
val loc = proj.fromPixels(e!!.x.toInt(), e.y.toInt()) as GeoPoint
|
||||
marker.position = loc
|
||||
mapView.invalidate()
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
mapView.overlays.add(marker)
|
||||
|
||||
val applyButton = findViewById<Button>(R.id.apply_location_button)
|
||||
applyButton.setOnClickListener {
|
||||
val bundle = Bundle()
|
||||
bundle.putFloat("latitude", marker.position.latitude.toFloat())
|
||||
bundle.putFloat("longitude", marker.position.longitude.toFloat())
|
||||
setResult(RESULT_OK, intent.putExtra("location", bundle))
|
||||
finish()
|
||||
}
|
||||
|
||||
val setPreciseLocationButton = findViewById<Button>(R.id.set_precise_location_button)
|
||||
|
||||
setPreciseLocationButton.setOnClickListener {
|
||||
val locationDialog = layoutInflater.inflate(R.layout.precise_location_dialog, null)
|
||||
val dialogLatitude = locationDialog.findViewById<EditText>(R.id.dialog_latitude).also { it.setText(marker.position.latitude.toString()) }
|
||||
val dialogLongitude = locationDialog.findViewById<EditText>(R.id.dialog_longitude).also { it.setText(marker.position.longitude.toString()) }
|
||||
|
||||
AlertDialog.Builder(this)
|
||||
.setView(locationDialog)
|
||||
.setTitle("Set a precise location")
|
||||
.setPositiveButton("Set") { _, _ ->
|
||||
val latitude = dialogLatitude.text.toString().toDoubleOrNull()
|
||||
val longitude = dialogLongitude.text.toString().toDoubleOrNull()
|
||||
if (latitude != null && longitude != null) {
|
||||
val preciseLocation = GeoPoint(latitude, longitude)
|
||||
mapView.controller.setCenter(preciseLocation)
|
||||
marker.position = preciseLocation
|
||||
mapView.invalidate()
|
||||
}
|
||||
}.setNegativeButton("Cancel") { _, _ -> }.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDetach()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user