refactor: download manager ui (#69)
* ui changes * fix more stuff * fix: set ffmpeg preset to ultrafast * refactor: ui tweaks getIdentifier function * feat: download manager filter * add placeholder bitmoji * change bitmoji blank color * add settings page (not done) * setting page impl * confirmation dialog * update theme * remove snap context buttons * fix: delete cache * fix: bitmoji icon --------- Co-authored-by: rhunk <101876869+rhunk@users.noreply.github.com>
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
|
||||
<activity
|
||||
android:name=".ui.download.DownloadManagerActivity"
|
||||
android:theme="@style/AppTheme"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
package me.rhunk.snapenhance.bridge.common.impl.file
|
||||
|
||||
import android.content.Context
|
||||
import java.io.File
|
||||
|
||||
enum class BridgeFileType(val value: Int, val fileName: String, val isDatabase: Boolean = false) {
|
||||
CONFIG(0, "config.json"),
|
||||
MAPPINGS(1, "mappings.json"),
|
||||
MESSAGE_LOGGER_DATABASE(2, "message_logger.db", true),
|
||||
STEALTH(3, "stealth.txt"),
|
||||
ANTI_AUTO_DOWNLOAD(4, "anti_auto_download.txt"),
|
||||
ANTI_AUTO_SAVE(5, "anti_auto_save.txt"),
|
||||
AUTO_UPDATER_TIMESTAMP(6, "auto_updater_timestamp.txt"),
|
||||
PINNED_CONVERSATIONS(7, "pinned_conversations.txt");
|
||||
|
||||
enum class BridgeFileType(val value: Int, val fileName: String, val displayName: String, val isDatabase: Boolean = false) {
|
||||
CONFIG(0, "config.json", "Config"),
|
||||
MAPPINGS(1, "mappings.json", "Mappings"),
|
||||
MESSAGE_LOGGER_DATABASE(2, "message_logger.db", "Message Logger",true),
|
||||
STEALTH(3, "stealth.txt", "Stealth Conversations"),
|
||||
ANTI_AUTO_DOWNLOAD(4, "anti_auto_download.txt", "Anti Auto Download"),
|
||||
ANTI_AUTO_SAVE(5, "anti_auto_save.txt", "Anti Auto Save"),
|
||||
AUTO_UPDATER_TIMESTAMP(6, "auto_updater_timestamp.txt", "Auto Updater Timestamp"),
|
||||
PINNED_CONVERSATIONS(7, "pinned_conversations.txt", "Pinned Conversations");
|
||||
|
||||
fun resolve(context: Context): File = if (isDatabase) {
|
||||
context.getDatabasePath(fileName)
|
||||
} else {
|
||||
File(context.filesDir, fileName)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromValue(value: Int): BridgeFileType? {
|
||||
|
||||
@@ -5,10 +5,12 @@ import android.content.Context
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import me.rhunk.snapenhance.download.data.PendingDownload
|
||||
import me.rhunk.snapenhance.download.enums.DownloadStage
|
||||
import me.rhunk.snapenhance.ui.download.MediaFilter
|
||||
import me.rhunk.snapenhance.util.SQLiteDatabaseHelper
|
||||
|
||||
class DownloadTaskManager {
|
||||
private lateinit var taskDatabase: SQLiteDatabase
|
||||
private val pendingTasks = mutableMapOf<Int, PendingDownload>()
|
||||
private val cachedTasks = mutableMapOf<Int, PendingDownload>()
|
||||
|
||||
@SuppressLint("Range")
|
||||
@@ -44,7 +46,7 @@ class DownloadTaskManager {
|
||||
it.moveToFirst()
|
||||
it.getInt(0)
|
||||
}
|
||||
cachedTasks[task.id] = task
|
||||
pendingTasks[task.id] = task
|
||||
return task.id
|
||||
}
|
||||
|
||||
@@ -60,33 +62,62 @@ class DownloadTaskManager {
|
||||
task.id
|
||||
)
|
||||
)
|
||||
cachedTasks[task.id] = task
|
||||
//if the task is no longer active, move it to the cached tasks
|
||||
if (task.isJobActive()) {
|
||||
pendingTasks[task.id] = task
|
||||
} else {
|
||||
pendingTasks.remove(task.id)
|
||||
cachedTasks[task.id] = task
|
||||
}
|
||||
}
|
||||
|
||||
fun isEmpty(): Boolean {
|
||||
return cachedTasks.isEmpty()
|
||||
return cachedTasks.isEmpty() && pendingTasks.isEmpty()
|
||||
}
|
||||
|
||||
private fun removeTask(id: Int) {
|
||||
taskDatabase.execSQL("DELETE FROM tasks WHERE id = ?", arrayOf(id))
|
||||
cachedTasks.remove(id)
|
||||
pendingTasks.remove(id)
|
||||
}
|
||||
|
||||
fun removeTask(task: PendingDownload) {
|
||||
removeTask(task.id)
|
||||
}
|
||||
|
||||
fun queryAllTasks(): Map<Int, PendingDownload> {
|
||||
cachedTasks.putAll(queryTasks(
|
||||
from = cachedTasks.values.lastOrNull()?.id ?: Int.MAX_VALUE,
|
||||
amount = 20
|
||||
fun queryAllTasks(filter: MediaFilter): Map<Int, PendingDownload> {
|
||||
val isPendingFilter = filter == MediaFilter.PENDING
|
||||
val tasks = mutableMapOf<Int, PendingDownload>()
|
||||
|
||||
tasks.putAll(pendingTasks.filter { isPendingFilter || filter.matches(it.value.mediaDisplayType) })
|
||||
if (isPendingFilter) {
|
||||
return tasks.toSortedMap(reverseOrder())
|
||||
}
|
||||
|
||||
tasks.putAll(queryTasks(
|
||||
from = tasks.values.lastOrNull()?.id ?: Int.MAX_VALUE,
|
||||
amount = 30,
|
||||
filter = filter
|
||||
))
|
||||
return cachedTasks.toSortedMap(reverseOrder())
|
||||
|
||||
return tasks.toSortedMap(reverseOrder())
|
||||
}
|
||||
|
||||
@SuppressLint("Range")
|
||||
fun queryTasks(from: Int, amount: Int = 20): Map<Int, PendingDownload> {
|
||||
val cursor = taskDatabase.rawQuery("SELECT * FROM tasks WHERE id < ? ORDER BY id DESC LIMIT ?", arrayOf(from.toString(), amount.toString()))
|
||||
fun queryTasks(from: Int, amount: Int = 20, filter: MediaFilter = MediaFilter.NONE): Map<Int, PendingDownload> {
|
||||
if (filter == MediaFilter.PENDING) {
|
||||
return emptyMap()
|
||||
}
|
||||
|
||||
val cursor = taskDatabase.rawQuery(
|
||||
"SELECT * FROM tasks WHERE id < ? AND mediaDisplayType LIKE ? ORDER BY id DESC LIMIT ?",
|
||||
arrayOf(
|
||||
from.toString(),
|
||||
filter.mediaDisplayType.let { if (it == null) "%" else "%$it" },
|
||||
amount.toString()
|
||||
)
|
||||
)
|
||||
|
||||
val result = sortedMapOf<Int, PendingDownload>()
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
@@ -107,11 +138,13 @@ class DownloadTaskManager {
|
||||
result[task.id] = task
|
||||
}
|
||||
cursor.close()
|
||||
|
||||
return result.toSortedMap(reverseOrder())
|
||||
}
|
||||
|
||||
fun removeAllTasks() {
|
||||
taskDatabase.execSQL("DELETE FROM tasks")
|
||||
cachedTasks.clear()
|
||||
pendingTasks.clear()
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import me.rhunk.snapenhance.features.impl.spying.MessageLogger
|
||||
import me.rhunk.snapenhance.hook.HookAdapter
|
||||
import me.rhunk.snapenhance.hook.HookStage
|
||||
import me.rhunk.snapenhance.hook.Hooker
|
||||
import me.rhunk.snapenhance.ui.download.MediaFilter
|
||||
import me.rhunk.snapenhance.util.snap.EncryptionHelper
|
||||
import me.rhunk.snapenhance.util.snap.MediaDownloaderHelper
|
||||
import me.rhunk.snapenhance.util.snap.MediaType
|
||||
@@ -193,7 +194,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam
|
||||
|
||||
val author = context.database.getFriendInfo(senderId) ?: return
|
||||
val authorUsername = author.usernameForSorting!!
|
||||
downloadOperaMedia(provideClientDownloadManager(authorUsername, authorUsername, "Chat Media", friendInfo = author), mediaInfoMap)
|
||||
downloadOperaMedia(provideClientDownloadManager(authorUsername, authorUsername, MediaFilter.CHAT_MEDIA.mediaDisplayType, friendInfo = author), mediaInfoMap)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -209,7 +210,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam
|
||||
val author = context.database.getFriendInfo(if (storyUserId == "null") context.database.getMyUserId()!! else storyUserId) ?: return
|
||||
val authorName = author.usernameForSorting!!
|
||||
|
||||
downloadOperaMedia(provideClientDownloadManager(authorName, authorName, "Story", friendInfo = author), mediaInfoMap, )
|
||||
downloadOperaMedia(provideClientDownloadManager(authorName, authorName, MediaFilter.STORY.mediaDisplayType, friendInfo = author), mediaInfoMap, )
|
||||
return
|
||||
}
|
||||
|
||||
@@ -227,7 +228,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam
|
||||
|
||||
//spotlight
|
||||
if (snapSource == "SINGLE_SNAP_STORY" && (forceDownload || canAutoDownload("spotlight"))) {
|
||||
downloadOperaMedia(provideClientDownloadManager("Spotlight", mediaDisplayType = "Spotlight", mediaDisplaySource = paramMap["TIME_STAMP"].toString()), mediaInfoMap)
|
||||
downloadOperaMedia(provideClientDownloadManager("Spotlight", mediaDisplayType = MediaFilter.SPOTLIGHT.mediaDisplayType, mediaDisplaySource = paramMap["TIME_STAMP"].toString()), mediaInfoMap)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -383,7 +384,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam
|
||||
runCatching {
|
||||
if (!isPreviewMode) {
|
||||
val encryptionKeys = EncryptionHelper.getEncryptionKeys(contentType, messageReader, isArroyo = isArroyoMessage)
|
||||
provideClientDownloadManager(authorName, authorName, "Chat Media", friendInfo = friendInfo).downloadMedia(
|
||||
provideClientDownloadManager(authorName, authorName, MediaFilter.CHAT_MEDIA.mediaDisplayType, friendInfo = friendInfo).downloadMedia(
|
||||
Base64.UrlSafe.encode(urlProto),
|
||||
DownloadMediaType.PROTO_MEDIA,
|
||||
encryption = encryptionKeys?.toKeyPair()
|
||||
|
||||
@@ -19,19 +19,21 @@ class UITweaks : Feature("UITweaks", loadParams = FeatureLoadParams.ACTIVITY_CRE
|
||||
val isImmersiveCamera = context.config.bool(ConfigProperty.IMMERSIVE_CAMERA_PREVIEW)
|
||||
val resources = context.resources
|
||||
|
||||
fun findIdentifier(name: String, defType: String) = resources.getIdentifier(name, defType, Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
|
||||
val displayMetrics = context.resources.displayMetrics
|
||||
|
||||
val capriViewfinderDefaultCornerRadius = resources.getIdentifier("capri_viewfinder_default_corner_radius", "dimen", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val ngsHovaNavLargerCameraButtonSize = resources.getIdentifier("ngs_hova_nav_larger_camera_button_size", "dimen", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val fullScreenSurfaceView = resources.getIdentifier("full_screen_surface_view", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val capriViewfinderDefaultCornerRadius = findIdentifier("capri_viewfinder_default_corner_radius", "dimen")
|
||||
val ngsHovaNavLargerCameraButtonSize = findIdentifier("ngs_hova_nav_larger_camera_button_size", "dimen")
|
||||
val fullScreenSurfaceView = findIdentifier("full_screen_surface_view", "id")
|
||||
|
||||
val callButtonsStub = resources.getIdentifier("call_buttons_stub", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val callButton1 = resources.getIdentifier("friend_action_button3", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val callButton2 = resources.getIdentifier("friend_action_button4", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val callButtonsStub = findIdentifier("call_buttons_stub", "id")
|
||||
val callButton1 = findIdentifier("friend_action_button3", "id")
|
||||
val callButton2 = findIdentifier("friend_action_button4", "id")
|
||||
|
||||
val chatNoteRecordButton = resources.getIdentifier("chat_note_record_button", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val chatInputBarSticker = resources.getIdentifier("chat_input_bar_sticker", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val chatInputBarCognac = resources.getIdentifier("chat_input_bar_cognac", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val chatNoteRecordButton = findIdentifier("chat_note_record_button", "id")
|
||||
val chatInputBarSticker = findIdentifier("chat_input_bar_sticker", "id")
|
||||
val chatInputBarCognac = findIdentifier("chat_input_bar_cognac", "id")
|
||||
|
||||
Resources::class.java.methods.first { it.name == "getDimensionPixelSize"}.hook(HookStage.AFTER,
|
||||
{ isImmersiveCamera }
|
||||
|
||||
@@ -22,9 +22,9 @@ class ActionManager(
|
||||
actions[action.nameKey] = action
|
||||
}
|
||||
override fun init() {
|
||||
load(CleanCache::class)
|
||||
load(ClearMessageLogger::class)
|
||||
load(RefreshMappings::class)
|
||||
//load(CleanCache::class)
|
||||
//load(ClearMessageLogger::class)
|
||||
//load(RefreshMappings::class)
|
||||
load(OpenMap::class)
|
||||
load(CheckForUpdates::class)
|
||||
load(ExportChatMessages::class)
|
||||
|
||||
@@ -131,7 +131,7 @@ class DownloadListAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
holder.bitmojiIcon.visibility = View.GONE
|
||||
holder.bitmojiIcon.setImageResource(R.drawable.bitmoji_blank)
|
||||
|
||||
pendingDownload.iconUrl?.let { url ->
|
||||
thread(start = true) {
|
||||
@@ -141,7 +141,6 @@ class DownloadListAdapter(
|
||||
}
|
||||
Handler(holder.view.context.mainLooper).post {
|
||||
holder.bitmojiIcon.setImageBitmap(iconBitmap)
|
||||
holder.bitmojiIcon.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,33 @@ 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.graphics.drawable.ColorDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.PowerManager
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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.BuildConfig
|
||||
import me.rhunk.snapenhance.R
|
||||
import me.rhunk.snapenhance.download.MediaDownloadReceiver
|
||||
import me.rhunk.snapenhance.download.data.PendingDownload
|
||||
|
||||
class DownloadManagerActivity : Activity() {
|
||||
private val backCallbacks = mutableListOf<() -> Unit>()
|
||||
private val fetchedDownloadTasks = mutableListOf<PendingDownload>()
|
||||
private var listFilter = MediaFilter.NONE
|
||||
|
||||
private val downloadTaskManager by lazy {
|
||||
MediaDownloadReceiver.downloadTaskManager.also { it.init(this) }
|
||||
}
|
||||
|
||||
private val preferences by lazy {
|
||||
getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
@@ -30,21 +40,47 @@ class DownloadManagerActivity : Activity() {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("BatteryLife", "NotifyDataSetChanged")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val downloadTaskManager = MediaDownloadReceiver.downloadTaskManager.also { it.init(this) }
|
||||
|
||||
actionBar?.apply {
|
||||
title = "Download Manager"
|
||||
setBackgroundDrawable(ColorDrawable(getColor(R.color.actionBarColor)))
|
||||
}
|
||||
setContentView(R.layout.download_manager_activity)
|
||||
|
||||
fetchedDownloadTasks.addAll(downloadTaskManager.queryAllTasks().values)
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun updateListContent() {
|
||||
fetchedDownloadTasks.clear()
|
||||
fetchedDownloadTasks.addAll(downloadTaskManager.queryAllTasks(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)
|
||||
|
||||
setContentView(R.layout.download_manager_activity)
|
||||
|
||||
window.navigationBarColor = getColor(R.color.primaryBackground)
|
||||
findViewById<TextView>(R.id.title).text = resources.getString(R.string.app_name) + " " + BuildConfig.VERSION_NAME
|
||||
|
||||
findViewById<ImageButton>(R.id.settings_button).setOnClickListener {
|
||||
SettingLayoutInflater(this).inflate(findViewById<ViewGroup>(android.R.id.content))
|
||||
}
|
||||
|
||||
with(findViewById<RecyclerView>(R.id.download_list)) {
|
||||
layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this@DownloadManagerActivity)
|
||||
|
||||
adapter = DownloadListAdapter(fetchedDownloadTasks).apply {
|
||||
registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||
@@ -53,8 +89,6 @@ class DownloadManagerActivity : Activity() {
|
||||
})
|
||||
}
|
||||
|
||||
layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this@DownloadManagerActivity)
|
||||
|
||||
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
|
||||
override fun getMovementFlags(
|
||||
recyclerView: RecyclerView,
|
||||
@@ -99,7 +133,7 @@ class DownloadManagerActivity : Activity() {
|
||||
if (lastVisibleItemPosition == fetchedDownloadTasks.size - 1 && !isLoading) {
|
||||
isLoading = true
|
||||
|
||||
downloadTaskManager.queryTasks(fetchedDownloadTasks.last().id).forEach {
|
||||
downloadTaskManager.queryTasks(fetchedDownloadTasks.last().id, filter = listFilter).forEach {
|
||||
fetchedDownloadTasks.add(it.value)
|
||||
adapter?.notifyItemInserted(fetchedDownloadTasks.size - 1)
|
||||
}
|
||||
@@ -108,31 +142,57 @@ class DownloadManagerActivity : Activity() {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
with(this@DownloadManagerActivity.findViewById<Button>(R.id.remove_all_button)) {
|
||||
setOnClickListener {
|
||||
downloadTaskManager.removeAllTasks()
|
||||
fetchedDownloadTasks.removeIf {
|
||||
if (it.isJobActive()) it.cancel()
|
||||
true
|
||||
|
||||
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).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))
|
||||
}
|
||||
adapter?.notifyDataSetChanged()
|
||||
updateNoDownloadText()
|
||||
}
|
||||
}
|
||||
|
||||
this@DownloadManagerActivity.findViewById<Button>(R.id.remove_all_button).setOnClickListener {
|
||||
with(AlertDialog.Builder(this@DownloadManagerActivity)) {
|
||||
setTitle(R.string.remove_all_title)
|
||||
setMessage(R.string.remove_all_text)
|
||||
setPositiveButton("Yes") { _, _ ->
|
||||
downloadTaskManager.removeAllTasks()
|
||||
fetchedDownloadTasks.removeIf {
|
||||
if (it.isJobActive()) it.cancel()
|
||||
true
|
||||
}
|
||||
adapter?.notifyDataSetChanged()
|
||||
updateNoDownloadText()
|
||||
}
|
||||
setNegativeButton("Cancel") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateNoDownloadText()
|
||||
updateListContent()
|
||||
|
||||
if (preferences.getBoolean("ask_battery_optimisations", true)) {
|
||||
val pm = getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
|
||||
with(Intent()) {
|
||||
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
|
||||
data = Uri.parse("package:$packageName")
|
||||
startActivityForResult(this, 1)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,12 +205,6 @@ class DownloadManagerActivity : Activity() {
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
fetchedDownloadTasks.clear()
|
||||
fetchedDownloadTasks.addAll(MediaDownloadReceiver.downloadTaskManager.queryAllTasks().values)
|
||||
|
||||
with(findViewById<RecyclerView>(R.id.download_list)) {
|
||||
adapter?.notifyDataSetChanged()
|
||||
}
|
||||
updateNoDownloadText()
|
||||
updateListContent()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package me.rhunk.snapenhance.ui.download
|
||||
|
||||
enum class MediaFilter(
|
||||
val mediaDisplayType: String? = null
|
||||
) {
|
||||
NONE,
|
||||
PENDING,
|
||||
CHAT_MEDIA("Chat Media"),
|
||||
STORY("Story"),
|
||||
SPOTLIGHT("Spotlight");
|
||||
|
||||
fun matches(source: String?): Boolean {
|
||||
if (mediaDisplayType == null) return true
|
||||
if (source == null) return false
|
||||
return source.contains(mediaDisplayType, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
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.R
|
||||
import me.rhunk.snapenhance.bridge.common.impl.file.BridgeFileType
|
||||
import java.io.File
|
||||
|
||||
class SettingAdapter(
|
||||
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 SettingLayoutInflater(
|
||||
private val activity: DownloadManagerActivity
|
||||
) {
|
||||
private fun confirmAction(title: String, message: String, action: () -> Unit) {
|
||||
activity.runOnUiThread {
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton("Yes") { _, _ ->
|
||||
action()
|
||||
}
|
||||
.setNegativeButton("No") { _, _ -> }
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun inflate(parent: ViewGroup) {
|
||||
val settingsView = activity.layoutInflater.inflate(R.layout.settings_page, parent, false)
|
||||
|
||||
settingsView.findViewById<ImageButton>(R.id.settings_button).setOnClickListener {
|
||||
parent.removeView(settingsView)
|
||||
}
|
||||
|
||||
settingsView.findViewById<ListView>(R.id.setting_page_list).apply {
|
||||
adapter = SettingAdapter(activity, R.layout.setting_item, mutableListOf<Pair<String, () -> Unit>>().apply {
|
||||
add("Clear Cache" to {
|
||||
context.cacheDir.listFiles()?.forEach {
|
||||
it.deleteRecursively()
|
||||
}
|
||||
Toast.makeText(context, "Cache cleared", Toast.LENGTH_SHORT).show()
|
||||
})
|
||||
|
||||
BridgeFileType.values().forEach { fileType ->
|
||||
val actionName = "Clear ${fileType.displayName} File"
|
||||
add(actionName to {
|
||||
confirmAction(actionName, "Are you sure you want to clear ${fileType.displayName} file?") {
|
||||
fileType.resolve(context).deleteRecursively()
|
||||
Toast.makeText(context, "${fileType.displayName} file cleared", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
add("Reset All" to {
|
||||
confirmAction("Reset All", "Are you sure you want to reset all?") {
|
||||
arrayOf(context.cacheDir, context.filesDir, File(context.dataDir, "databases"), File(context.dataDir, "shared_prefs")).forEach {
|
||||
it.listFiles()?.forEach { file ->
|
||||
file.deleteRecursively()
|
||||
}
|
||||
}
|
||||
Toast.makeText(context, "Success!", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
})
|
||||
}.toTypedArray())
|
||||
}
|
||||
|
||||
activity.registerBackCallback {
|
||||
parent.removeView(settingsView)
|
||||
}
|
||||
|
||||
parent.addView(settingsView)
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,8 @@ object MediaDownloaderHelper {
|
||||
Executors.newSingleThreadExecutor())
|
||||
}
|
||||
|
||||
//TODO: implement setting parameters
|
||||
|
||||
suspend fun downloadDashChapterFile(
|
||||
dashPlaylist: File,
|
||||
output: File,
|
||||
@@ -82,7 +84,7 @@ object MediaDownloaderHelper {
|
||||
duration: Long?) {
|
||||
runFFmpegAsync(
|
||||
"-y", "-i", dashPlaylist.absolutePath, "-ss", "'${startTime}ms'", *(if (duration != null) arrayOf("-t", "'${duration}ms'") else arrayOf()),
|
||||
"-c:v", "libx264", "-threads", "6", "-q:v", "13", output.absolutePath
|
||||
"-c:v", "libx264", "-preset", "ultrafast", "-threads", "6", "-q:v", "13", output.absolutePath
|
||||
)
|
||||
}
|
||||
|
||||
@@ -94,7 +96,7 @@ object MediaDownloaderHelper {
|
||||
runFFmpegAsync(
|
||||
"-y", "-i", media.absolutePath, "-i", overlay.absolutePath,
|
||||
"-filter_complex", "\"[0]scale2ref[img][vid];[img]setsar=1[img];[vid]nullsink;[img][1]overlay=(W-w)/2:(H-h)/2,scale=2*trunc(iw*sar/2):2*trunc(ih/2)\"",
|
||||
"-c:v", "libx264", "-b:v", "5M", "-c:a", "copy", "-threads", "6", output.absolutePath
|
||||
"-c:v", "libx264", "-b:v", "5M", "-c:a", "copy", "-preset", "ultrafast", "-threads", "6", output.absolutePath
|
||||
)
|
||||
}
|
||||
}
|
||||
11
app/src/main/res/drawable/back_arrow.xml
Normal file
11
app/src/main/res/drawable/back_arrow.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<vector android:height="25dp" android:viewportHeight="512"
|
||||
android:viewportWidth="512" android:width="25dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#00000000"
|
||||
android:pathData="M244,400l-144,-144l144,-144"
|
||||
android:strokeColor="#FFFFFF" android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" android:strokeWidth="48"/>
|
||||
<path android:fillColor="#00000000"
|
||||
android:pathData="M120,256L412,256"
|
||||
android:strokeColor="#FFFFFF" android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" android:strokeWidth="48"/>
|
||||
</vector>
|
||||
11
app/src/main/res/drawable/bitmoji_blank.xml
Normal file
11
app/src/main/res/drawable/bitmoji_blank.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="90dp"
|
||||
android:height="90dp"
|
||||
android:viewportWidth="90"
|
||||
android:viewportHeight="90">
|
||||
<path
|
||||
android:pathData="M45,90.1c10.8,0 20.8,-3.8 28.6,-10.2c-1.4,-2.1 -3,-3.6 -4.7,-5c-5.2,-4.1 -12.6,-5.6 -17.7,-6.5l-0.2,-2c7.8,-4.6 9.7,-9.5 12.8,-19.8l0.1,-0.7c0,0 2.7,-1.1 3.1,-6.1c0.6,-6.8 -2.2,-4.8 -2.2,-5.3C65.1,31 65,26.4 64,23c-2.1,-7.3 -9.2,-13.1 -19,-13.1S28.1,15.6 26,23c-1,3.4 -1.1,8 -0.8,11.6c0,0.5 -2.7,-1.5 -2.2,5.3c0.4,5 3.1,6.1 3.1,6.1l0.1,0.7c3.1,10.3 5,15.2 12.8,19.8l-0.2,2c-5,0.9 -12.5,2.4 -17.7,6.5c-1.7,1.4 -3.3,2.9 -4.7,5C24.2,86.3 34.2,90.1 45,90.1z"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#979797"
|
||||
android:strokeColor="#000000"/>
|
||||
</vector>
|
||||
11
app/src/main/res/drawable/settings_icon.xml
Normal file
11
app/src/main/res/drawable/settings_icon.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="30dp"
|
||||
android:height="30dp"
|
||||
android:viewportWidth="50"
|
||||
android:viewportHeight="50">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M40.843,22.134C41.511,22.249 42,22.829 42,23.507v2.985c0,0.678 -0.489,1.258 -1.157,1.373l-2.777,0.478c-0.321,1.258 -0.816,2.443 -1.462,3.531l1.626,2.301c0.391,0.554 0.327,1.31 -0.153,1.789l-2.111,2.111c-0.538,0.517 -1.277,0.521 -1.789,0.153l-2.301,-1.626c-1.088,0.646 -2.273,1.141 -3.531,1.462l-0.478,2.777C27.751,41.511 27.171,42 26.492,42h-2.985c-0.678,0 -1.258,-0.489 -1.373,-1.157l-0.478,-2.777c-1.258,-0.321 -2.443,-0.816 -3.531,-1.462l-2.301,1.626c-0.534,0.381 -1.283,0.343 -1.789,-0.153l-2.111,-2.111c-0.48,-0.48 -0.544,-1.235 -0.153,-1.789l1.626,-2.301c-0.646,-1.088 -1.141,-2.273 -1.462,-3.531l-2.777,-0.478C8.489,27.751 8,27.171 8,26.492v-2.985c0,-0.678 0.489,-1.258 1.157,-1.373l2.777,-0.478c0.321,-1.258 0.816,-2.443 1.462,-3.531l-1.626,-2.301c-0.391,-0.554 -0.327,-1.31 0.153,-1.789l2.111,-2.111c0.596,-0.579 1.369,-0.456 1.789,-0.153l2.301,1.626c1.088,-0.646 2.273,-1.141 3.531,-1.462l0.478,-2.777C22.249,8.489 22.829,8 23.508,8h2.985c0.678,0 1.258,0.489 1.373,1.157l0.478,2.777c1.258,0.321 2.443,0.816 3.531,1.462l2.301,-1.626c0.617,-0.414 1.351,-0.282 1.789,0.153l2.111,2.111c0.48,0.48 0.544,1.235 0.153,1.789l-1.626,2.301c0.646,1.088 1.141,2.273 1.462,3.531L40.843,22.134zM25,31.955c3.841,0 6.955,-3.114 6.955,-6.955c0,-3.841 -3.114,-6.955 -6.955,-6.955S18.045,21.159 18.045,25C18.045,28.841 21.159,31.955 25,31.955z"
|
||||
tools:ignore="VectorPath" />
|
||||
</vector>
|
||||
BIN
app/src/main/res/font/avenir_next_bold.ttf
Normal file
BIN
app/src/main/res/font/avenir_next_bold.ttf
Normal file
Binary file not shown.
@@ -1,60 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/download_manager_activity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/primaryBackground"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/title_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/borderColor"
|
||||
android:layout_gravity="bottom" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/primaryText"
|
||||
android:textSize="23sp"
|
||||
android:fontFamily="@font/avenir_next_bold" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/settings_button"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@null"
|
||||
android:src="@drawable/settings_icon"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:padding="8dp"
|
||||
android:contentDescription="@string/settings" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/category_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:background="@color/secondaryBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:layoutDirection="rtl">
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="right"
|
||||
android:padding="10dp"
|
||||
tools:ignore="RtlHardcoded">
|
||||
<Button
|
||||
android:id="@+id/remove_all_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:background="@drawable/action_button_cancel"
|
||||
android:padding="5dp"
|
||||
android:text="Remove All"
|
||||
android:textColor="@color/darkText" />
|
||||
</RelativeLayout>
|
||||
<TextView
|
||||
android:id="@+id/all_category"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:fontFamily="@font/avenir_next_medium"
|
||||
android:gravity="center"
|
||||
android:text="@string/all_category"
|
||||
android:textColor="@color/focusedCategoryColor" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pending_category"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:fontFamily="@font/avenir_next_medium"
|
||||
android:gravity="center"
|
||||
android:text="@string/pending_category"
|
||||
android:textColor="@color/primaryText" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/snap_category"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:fontFamily="@font/avenir_next_medium"
|
||||
android:gravity="center"
|
||||
android:text="@string/snap_category"
|
||||
android:textColor="@color/primaryText" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/story_category"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:fontFamily="@font/avenir_next_medium"
|
||||
android:gravity="center"
|
||||
android:text="@string/story_category"
|
||||
android:textColor="@color/primaryText" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/spotlight_category"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:fontFamily="@font/avenir_next_medium"
|
||||
android:gravity="center"
|
||||
android:text="@string/spotlight_category"
|
||||
android:textColor="@color/primaryText" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/download_list_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/download_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/no_download_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foregroundGravity="clip_horizontal"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="40dp"
|
||||
android:text="No downloads"
|
||||
android:text="@string/no_downloads"
|
||||
android:textColor="@color/primaryText" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
<FrameLayout
|
||||
android:id="@+id/floating_button_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/remove_all_button"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="45dp"
|
||||
android:background="@drawable/action_button_cancel"
|
||||
android:padding="5dp"
|
||||
android:text="@string/remove_all"
|
||||
android:textColor="@color/darkText"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
android:layout_marginBottom="5dp"/>
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -1,37 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:layout_margin="5dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:background="@drawable/download_manager_item_background"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="5dp">
|
||||
android:padding="10dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/download_manager_item_background"
|
||||
android:orientation="horizontal"
|
||||
android:padding="5dp"
|
||||
android:padding="10dp"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bitmoji_icon"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_margin="5dp"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="10dp"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="5dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_title"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -44,13 +51,12 @@
|
||||
android:id="@+id/item_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/secondaryText" />
|
||||
android:textColor="@color/secondaryText"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_status"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -60,11 +66,12 @@
|
||||
|
||||
<Button
|
||||
android:id="@+id/item_action_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="39dp"
|
||||
android:background="@drawable/action_button_cancel"
|
||||
android:padding="5dp"
|
||||
android:text="Cancel"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:text="@string/cancel"
|
||||
android:textColor="@color/darkText"
|
||||
tools:ignore="ButtonOrder,HardcodedText" />
|
||||
</LinearLayout>
|
||||
tools:ignore="ButtonOrder" />
|
||||
</LinearLayout>
|
||||
|
||||
19
app/src/main/res/layout/setting_item.xml
Normal file
19
app/src/main/res/layout/setting_item.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/preference_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/feature_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:text=""
|
||||
android:textColor="@color/primaryText"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</LinearLayout>
|
||||
52
app/src/main/res/layout/settings_page.xml
Normal file
52
app/src/main/res/layout/settings_page.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/setting_page"
|
||||
android:clickable="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/primaryBackground"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/title_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/settings_button"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@null"
|
||||
android:src="@drawable/back_arrow"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:padding="8dp"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/borderColor"
|
||||
android:layout_gravity="bottom" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="@string/settings"
|
||||
android:textColor="@color/primaryText"
|
||||
android:textSize="23sp"
|
||||
android:fontFamily="@font/avenir_next_bold" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<ListView
|
||||
android:id="@+id/setting_page_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:listSelector="@android:color/transparent"
|
||||
android:orientation="vertical">
|
||||
</ListView>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -9,4 +9,6 @@
|
||||
<color name="secondaryText">#999999</color>
|
||||
<color name="errorColor">#DF4C5C</color>
|
||||
<color name="successColor">#4FABF8</color>
|
||||
<color name="borderColor">#424242</color>
|
||||
<color name="focusedCategoryColor">#4FABF8</color>
|
||||
</resources>
|
||||
@@ -1,3 +1,15 @@
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Snap Enhance</string>
|
||||
<string name="app_name" translatable="false">SnapEnhance</string>
|
||||
<string name="remove_all_title">Remove all Downloads</string>
|
||||
<string name="remove_all_text">Are you sure you want to do this?</string>
|
||||
<string name="remove_all">Remove All</string>
|
||||
<string name="no_downloads">No downloads</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="all_category">All</string>
|
||||
<string name="pending_category">Pending</string>
|
||||
<string name="snap_category">Snaps</string>
|
||||
<string name="story_category">Stories</string>
|
||||
<string name="spotlight_category">Spotlight</string>
|
||||
<string name="settings">Settings</string>
|
||||
<string name="refresh_mappings">Refresh Mappings</string>
|
||||
</resources>
|
||||
@@ -2,5 +2,7 @@
|
||||
<resources>
|
||||
<style name="AppTheme">
|
||||
<item name="android:fontFamily">@font/avenir_next_medium</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
</style>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user