1.再次优化扫描文件性能,异步获取缩略图
2.添加列表item,更多设置选项对话框 3.修复数据库键值,不使用hash来作为键值,依据文件路径来判定 4.修复密码输入框实现,使用自带的错误等提示TextInputEditText
This commit is contained in:
parent
ff14a8f3ee
commit
369dc9d129
@ -19,18 +19,18 @@ interface BookmarkDao {
|
|||||||
@Query("SELECT * FROM bookmarks WHERE id = :bookmarkId")
|
@Query("SELECT * FROM bookmarks WHERE id = :bookmarkId")
|
||||||
suspend fun getById(bookmarkId: Long): BookmarkEntity?
|
suspend fun getById(bookmarkId: Long): BookmarkEntity?
|
||||||
|
|
||||||
@Query("SELECT * FROM bookmarks WHERE pdfHash = :pdfHash ORDER BY pageNumber ASC, createTime ASC")
|
@Query("SELECT * FROM bookmarks WHERE filePath = :filePath ORDER BY pageNumber ASC, createTime ASC")
|
||||||
fun getBookmarksByPdf(pdfHash: String): Flow<List<BookmarkEntity>>
|
fun getBookmarksByPdf(filePath: String): Flow<List<BookmarkEntity>>
|
||||||
|
|
||||||
@Query("SELECT * FROM bookmarks WHERE pdfHash = :pdfHash AND pageNumber = :pageNumber")
|
@Query("SELECT * FROM bookmarks WHERE filePath = :filePath AND pageNumber = :pageNumber")
|
||||||
suspend fun getBookmarksByPage(pdfHash: String, pageNumber: Int): List<BookmarkEntity>
|
suspend fun getBookmarksByPage(filePath: String, pageNumber: Int): List<BookmarkEntity>
|
||||||
|
|
||||||
@Query("SELECT COUNT(*) FROM bookmarks WHERE pdfHash = :pdfHash")
|
@Query("SELECT COUNT(*) FROM bookmarks WHERE filePath = :filePath")
|
||||||
suspend fun getBookmarkCount(pdfHash: String): Int
|
suspend fun getBookmarkCount(filePath: String): Int
|
||||||
|
|
||||||
@Query("DELETE FROM bookmarks WHERE pdfHash = :pdfHash")
|
@Query("DELETE FROM bookmarks WHERE filePath = :filePath")
|
||||||
suspend fun deleteAllByPdf(pdfHash: String)
|
suspend fun deleteAllByPdf(filePath: String)
|
||||||
|
|
||||||
@Query("DELETE FROM bookmarks WHERE pdfHash = :pdfHash AND pageNumber = :pageNumber")
|
@Query("DELETE FROM bookmarks WHERE filePath = :filePath AND pageNumber = :pageNumber")
|
||||||
suspend fun deleteByPage(pdfHash: String, pageNumber: Int)
|
suspend fun deleteByPage(filePath: String, pageNumber: Int)
|
||||||
}
|
}
|
||||||
@ -19,21 +19,21 @@ interface NoteDao {
|
|||||||
@Query("SELECT * FROM notes WHERE id = :noteId")
|
@Query("SELECT * FROM notes WHERE id = :noteId")
|
||||||
suspend fun getById(noteId: Long): NoteEntity?
|
suspend fun getById(noteId: Long): NoteEntity?
|
||||||
|
|
||||||
@Query("SELECT * FROM notes WHERE pdfHash = :pdfHash ORDER BY pageNumber ASC, createTime ASC")
|
@Query("SELECT * FROM notes WHERE filePath = :filePath ORDER BY pageNumber ASC, createTime ASC")
|
||||||
fun getNotesByPdf(pdfHash: String): Flow<List<NoteEntity>>
|
fun getNotesByPdf(filePath: String): Flow<List<NoteEntity>>
|
||||||
|
|
||||||
@Query("SELECT * FROM notes WHERE pdfHash = :pdfHash AND pageNumber = :pageNumber")
|
@Query("SELECT * FROM notes WHERE filePath = :filePath AND pageNumber = :pageNumber")
|
||||||
suspend fun getNotesByPage(pdfHash: String, pageNumber: Int): List<NoteEntity>
|
suspend fun getNotesByPage(filePath: String, pageNumber: Int): List<NoteEntity>
|
||||||
|
|
||||||
@Query("SELECT * FROM notes WHERE pdfHash = :pdfHash AND noteType = :noteType")
|
@Query("SELECT * FROM notes WHERE filePath = :filePath AND noteType = :noteType")
|
||||||
fun getNotesByType(pdfHash: String, noteType: String): Flow<List<NoteEntity>>
|
fun getNotesByType(filePath: String, noteType: String): Flow<List<NoteEntity>>
|
||||||
|
|
||||||
@Query("SELECT COUNT(*) FROM notes WHERE pdfHash = :pdfHash")
|
@Query("SELECT COUNT(*) FROM notes WHERE filePath = :filePath")
|
||||||
suspend fun getNoteCount(pdfHash: String): Int
|
suspend fun getNoteCount(filePath: String): Int
|
||||||
|
|
||||||
@Query("DELETE FROM notes WHERE pdfHash = :pdfHash")
|
@Query("DELETE FROM notes WHERE filePath = :filePath")
|
||||||
suspend fun deleteAllByPdf(pdfHash: String)
|
suspend fun deleteAllByPdf(filePath: String)
|
||||||
|
|
||||||
@Query("DELETE FROM notes WHERE pdfHash = :pdfHash AND pageNumber = :pageNumber")
|
@Query("DELETE FROM notes WHERE filePath = :filePath AND pageNumber = :pageNumber")
|
||||||
suspend fun deleteByPage(pdfHash: String, pageNumber: Int)
|
suspend fun deleteByPage(filePath: String, pageNumber: Int)
|
||||||
}
|
}
|
||||||
@ -34,6 +34,6 @@ interface PdfDocumentDao {
|
|||||||
@Delete
|
@Delete
|
||||||
suspend fun delete(document: PdfDocumentEntity)
|
suspend fun delete(document: PdfDocumentEntity)
|
||||||
|
|
||||||
@Query("DELETE FROM pdf_documents WHERE fileHash = :fileHash")
|
@Query("DELETE FROM pdf_documents WHERE filePath = :filePath")
|
||||||
suspend fun deleteByHash(fileHash: String)
|
suspend fun deleteByPath(filePath: String)
|
||||||
}
|
}
|
||||||
@ -11,25 +11,25 @@ interface RecentReadDao {
|
|||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun insertOrUpdate(recentRead: RecentReadEntity)
|
suspend fun insertOrUpdate(recentRead: RecentReadEntity)
|
||||||
|
|
||||||
@Query("SELECT * FROM recently_read WHERE pdfHash = :pdfHash")
|
@Query("SELECT * FROM recently_read WHERE filePath = :filePath")
|
||||||
suspend fun getByPdfHash(pdfHash: String): RecentReadEntity?
|
suspend fun getByPdfHash(filePath: String): RecentReadEntity?
|
||||||
|
|
||||||
@Query("""
|
@Query("""
|
||||||
SELECT pdf_documents.*
|
SELECT pdf_documents.*
|
||||||
FROM pdf_documents
|
FROM pdf_documents
|
||||||
INNER JOIN recently_read ON pdf_documents.fileHash = recently_read.pdfHash
|
INNER JOIN recently_read ON pdf_documents.filePath = recently_read.filePath
|
||||||
ORDER BY recently_read.lastOpenedTime DESC
|
ORDER BY recently_read.lastOpenedTime DESC
|
||||||
""")
|
""")
|
||||||
fun getRecentReadDocuments(): Flow<List<PdfDocumentEntity>>
|
fun getRecentReadDocuments(): Flow<List<PdfDocumentEntity>>
|
||||||
|
|
||||||
@Query("UPDATE recently_read SET lastOpenedTime = :time, openedCount = openedCount + 1 WHERE pdfHash = :pdfHash")
|
@Query("UPDATE recently_read SET lastOpenedTime = :time, openedCount = openedCount + 1 WHERE filePath = :filePath")
|
||||||
suspend fun updateOpenTime(pdfHash: String, time: Long = System.currentTimeMillis())
|
suspend fun updateOpenTime(filePath: String, time: Long = System.currentTimeMillis())
|
||||||
|
|
||||||
@Query("UPDATE recently_read SET totalReadTime = totalReadTime + :additionalTime WHERE pdfHash = :pdfHash")
|
@Query("UPDATE recently_read SET totalReadTime = totalReadTime + :additionalTime WHERE filePath = :filePath")
|
||||||
suspend fun addReadTime(pdfHash: String, additionalTime: Long)
|
suspend fun addReadTime(filePath: String, additionalTime: Long)
|
||||||
|
|
||||||
@Query("DELETE FROM recently_read WHERE pdfHash = :pdfHash")
|
@Query("DELETE FROM recently_read WHERE filePath = :filePath")
|
||||||
suspend fun deleteByPdfHash(pdfHash: String)
|
suspend fun deleteByPdfPath(filePath: String)
|
||||||
|
|
||||||
@Query("DELETE FROM recently_read WHERE lastOpenedTime < :cutoffTime")
|
@Query("DELETE FROM recently_read WHERE lastOpenedTime < :cutoffTime")
|
||||||
suspend fun deleteOldRecents(cutoffTime: Long)
|
suspend fun deleteOldRecents(cutoffTime: Long)
|
||||||
|
|||||||
@ -9,17 +9,17 @@ import androidx.room.PrimaryKey
|
|||||||
tableName = "bookmarks",
|
tableName = "bookmarks",
|
||||||
foreignKeys = [ForeignKey(
|
foreignKeys = [ForeignKey(
|
||||||
entity = PdfDocumentEntity::class,
|
entity = PdfDocumentEntity::class,
|
||||||
parentColumns = ["fileHash"],
|
parentColumns = ["filePath"],
|
||||||
childColumns = ["pdfHash"],
|
childColumns = ["filePath"],
|
||||||
onDelete = ForeignKey.CASCADE
|
onDelete = ForeignKey.CASCADE
|
||||||
)],
|
)],
|
||||||
indices = [Index(value = ["pdfHash"])]
|
indices = [Index(value = ["filePath"])]
|
||||||
)
|
)
|
||||||
data class BookmarkEntity(
|
data class BookmarkEntity(
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
val id: Long = 0,
|
val id: Long = 0,
|
||||||
|
|
||||||
val pdfHash: String, // 关联PdfDocumentEntity的fileHash
|
val filePath: String, // 关联PdfDocumentEntity的fileHash
|
||||||
val pageNumber: Int, // 页码(从0开始)
|
val pageNumber: Int, // 页码(从0开始)
|
||||||
val label: String, // 书签标签
|
val label: String, // 书签标签
|
||||||
val positionX: Float = 0f, // 页面内X位置
|
val positionX: Float = 0f, // 页面内X位置
|
||||||
|
|||||||
@ -9,17 +9,17 @@ import androidx.room.PrimaryKey
|
|||||||
tableName = "notes",
|
tableName = "notes",
|
||||||
foreignKeys = [ForeignKey(
|
foreignKeys = [ForeignKey(
|
||||||
entity = PdfDocumentEntity::class,
|
entity = PdfDocumentEntity::class,
|
||||||
parentColumns = ["fileHash"],
|
parentColumns = ["filePath"],
|
||||||
childColumns = ["pdfHash"],
|
childColumns = ["filePath"],
|
||||||
onDelete = ForeignKey.CASCADE
|
onDelete = ForeignKey.CASCADE
|
||||||
)],
|
)],
|
||||||
indices = [Index(value = ["pdfHash"])]
|
indices = [Index(value = ["filePath"])]
|
||||||
)
|
)
|
||||||
data class NoteEntity(
|
data class NoteEntity(
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
val id: Long = 0,
|
val id: Long = 0,
|
||||||
|
|
||||||
val pdfHash: String, // 关联PdfDocumentEntity的fileHash
|
val filePath: String, // 关联PdfDocumentEntity的fileHash
|
||||||
val pageNumber: Int, // 页码(从0开始)
|
val pageNumber: Int, // 页码(从0开始)
|
||||||
val noteType: String, // 注释类型: HIGHLIGHT, TEXT_NOTE, DRAWING
|
val noteType: String, // 注释类型: HIGHLIGHT, TEXT_NOTE, DRAWING
|
||||||
val content: String, // 注释内容(文本或序列化的绘制数据)
|
val content: String, // 注释内容(文本或序列化的绘制数据)
|
||||||
|
|||||||
@ -9,9 +9,9 @@ import kotlinx.parcelize.Parcelize
|
|||||||
@Entity(tableName = "pdf_documents")
|
@Entity(tableName = "pdf_documents")
|
||||||
data class PdfDocumentEntity(
|
data class PdfDocumentEntity(
|
||||||
@PrimaryKey
|
@PrimaryKey
|
||||||
val fileHash: String, // 文件内容哈希(MD5/SHA-1)
|
|
||||||
|
|
||||||
val filePath: String, // 当前文件路径
|
val filePath: String, // 当前文件路径
|
||||||
|
|
||||||
|
val fileHash: String? = null, // 文件内容哈希(MD5/SHA-1),扫描时不进行获取,需要做判定再单独获取
|
||||||
val fileName: String, // 文件名
|
val fileName: String, // 文件名
|
||||||
val fileSize: Long, // 文件大小(字节)
|
val fileSize: Long, // 文件大小(字节)
|
||||||
val lastModified: Long, // 文件最后修改时间
|
val lastModified: Long, // 文件最后修改时间
|
||||||
|
|||||||
@ -9,17 +9,17 @@ import androidx.room.PrimaryKey
|
|||||||
tableName = "recently_read",
|
tableName = "recently_read",
|
||||||
foreignKeys = [ForeignKey(
|
foreignKeys = [ForeignKey(
|
||||||
entity = PdfDocumentEntity::class,
|
entity = PdfDocumentEntity::class,
|
||||||
parentColumns = ["fileHash"],
|
parentColumns = ["filePath"],
|
||||||
childColumns = ["pdfHash"],
|
childColumns = ["filePath"],
|
||||||
onDelete = ForeignKey.CASCADE
|
onDelete = ForeignKey.CASCADE
|
||||||
)],
|
)],
|
||||||
indices = [Index(value = ["pdfHash"])]
|
indices = [Index(value = ["filePath"])]
|
||||||
)
|
)
|
||||||
data class RecentReadEntity(
|
data class RecentReadEntity(
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
val id: Long = 0,
|
val id: Long = 0,
|
||||||
|
|
||||||
val pdfHash: String, // 关联PdfDocumentEntity的fileHash
|
val filePath: String, // 关联PdfDocumentEntity的filePath
|
||||||
val lastOpenedTime: Long, // 最后打开时间
|
val lastOpenedTime: Long, // 最后打开时间
|
||||||
val openedCount: Int = 1, // 打开次数
|
val openedCount: Int = 1, // 打开次数
|
||||||
val totalReadTime: Long = 0, // 总阅读时长(毫秒)
|
val totalReadTime: Long = 0, // 总阅读时长(毫秒)
|
||||||
|
|||||||
@ -41,16 +41,16 @@ class PdfRepository private constructor(context: Context) {
|
|||||||
fun searchDocuments(query: String): Flow<List<PdfDocumentEntity>> =
|
fun searchDocuments(query: String): Flow<List<PdfDocumentEntity>> =
|
||||||
pdfDao.searchDocuments(query)
|
pdfDao.searchDocuments(query)
|
||||||
|
|
||||||
suspend fun updateFavoriteStatus(fileHash: String, isFavorite: Boolean) {
|
suspend fun updateFavoriteStatus(filePath: String, isFavorite: Boolean) {
|
||||||
val document = pdfDao.getByPath(fileHash)?.copy(
|
val document = pdfDao.getByPath(filePath)?.copy(
|
||||||
isFavorite = isFavorite,
|
isFavorite = isFavorite,
|
||||||
addedToFavoriteTime = if (isFavorite) System.currentTimeMillis() else null
|
addedToFavoriteTime = if (isFavorite) System.currentTimeMillis() else null
|
||||||
)
|
)
|
||||||
document?.let { pdfDao.update(it) }
|
document?.let { pdfDao.update(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateReadingProgress(fileHash: String, page: Int, progress: Float) {
|
suspend fun updateReadingProgress(filePath: String, page: Int, progress: Float) {
|
||||||
val document = pdfDao.getByPath(fileHash)?.copy(
|
val document = pdfDao.getByPath(filePath)?.copy(
|
||||||
lastOpenedTime = System.currentTimeMillis(),
|
lastOpenedTime = System.currentTimeMillis(),
|
||||||
lastReadPage = page,
|
lastReadPage = page,
|
||||||
readingProgress = progress
|
readingProgress = progress
|
||||||
@ -58,29 +58,37 @@ class PdfRepository private constructor(context: Context) {
|
|||||||
document?.let { pdfDao.update(it) }
|
document?.let { pdfDao.update(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updatePasswordStatus(fileHash: String, isPassword: Boolean) {
|
suspend fun updatePasswordStatus(filePath: String, isPassword: Boolean) {
|
||||||
val document = pdfDao.getByPath(fileHash)?.copy(
|
val document = pdfDao.getByPath(filePath)?.copy(
|
||||||
isPassword = isPassword
|
isPassword = isPassword
|
||||||
)
|
)
|
||||||
document?.let { pdfDao.update(it) }
|
document?.let { pdfDao.update(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updatePassword(fileHash: String, password: String?) {
|
suspend fun updatePassword(filePath: String, password: String?) {
|
||||||
val document = pdfDao.getByPath(fileHash)?.copy(
|
val document = pdfDao.getByPath(filePath)?.copy(
|
||||||
password = password
|
password = password
|
||||||
)
|
)
|
||||||
document?.let { pdfDao.update(it) }
|
document?.let { pdfDao.update(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun updateThumbnailPath(filePath: String, path: String) {
|
||||||
|
val document = pdfDao.getByPath(filePath)?.copy(
|
||||||
|
thumbnailPath = path,
|
||||||
|
)
|
||||||
|
document?.let { pdfDao.update(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 最近阅读相关操作
|
// 最近阅读相关操作
|
||||||
suspend fun addToRecent(pdfHash: String, page: Int = 0) {
|
suspend fun addToRecent(filePath: String, page: Int = 0) {
|
||||||
val existing = recentDao.getByPdfHash(pdfHash)
|
val existing = recentDao.getByPdfHash(filePath)
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
recentDao.updateOpenTime(pdfHash)
|
recentDao.updateOpenTime(filePath)
|
||||||
} else {
|
} else {
|
||||||
recentDao.insertOrUpdate(
|
recentDao.insertOrUpdate(
|
||||||
RecentReadEntity(
|
RecentReadEntity(
|
||||||
pdfHash = pdfHash,
|
filePath = filePath,
|
||||||
lastOpenedTime = System.currentTimeMillis()
|
lastOpenedTime = System.currentTimeMillis()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -113,7 +121,7 @@ class PdfRepository private constructor(context: Context) {
|
|||||||
// 组合查询
|
// 组合查询
|
||||||
suspend fun getPdfWithDetails(pdfHash: String): Flow<PdfDetails> {
|
suspend fun getPdfWithDetails(pdfHash: String): Flow<PdfDetails> {
|
||||||
return combine(
|
return combine(
|
||||||
pdfDao.getByPath(pdfHash)?.let { kotlinx.coroutines.flow.flowOf(it) }
|
pdfDao.getByHash(pdfHash)?.let { kotlinx.coroutines.flow.flowOf(it) }
|
||||||
?: kotlinx.coroutines.flow.flowOf(null),
|
?: kotlinx.coroutines.flow.flowOf(null),
|
||||||
bookmarkDao.getBookmarksByPdf(pdfHash),
|
bookmarkDao.getBookmarksByPdf(pdfHash),
|
||||||
noteDao.getNotesByPdf(pdfHash)
|
noteDao.getNotesByPdf(pdfHash)
|
||||||
@ -144,11 +152,11 @@ class PdfRepository private constructor(context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 数据清理
|
// 数据清理
|
||||||
suspend fun deleteDocument(fileHash: String) {
|
suspend fun deleteDocument(filePath: String) {
|
||||||
pdfDao.deleteByHash(fileHash)
|
pdfDao.deleteByPath(filePath)
|
||||||
recentDao.deleteByPdfHash(fileHash)
|
recentDao.deleteByPdfPath(filePath)
|
||||||
bookmarkDao.deleteAllByPdf(fileHash)
|
bookmarkDao.deleteAllByPdf(filePath)
|
||||||
noteDao.deleteAllByPdf(fileHash)
|
noteDao.deleteAllByPdf(filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@ -10,16 +10,12 @@ import com.all.pdfreader.pro.app.PDFReaderApplication
|
|||||||
import com.all.pdfreader.pro.app.R
|
import com.all.pdfreader.pro.app.R
|
||||||
import com.all.pdfreader.pro.app.databinding.ActivityMainBinding
|
import com.all.pdfreader.pro.app.databinding.ActivityMainBinding
|
||||||
import com.all.pdfreader.pro.app.ui.dialog.PermissionDialogFragment
|
import com.all.pdfreader.pro.app.ui.dialog.PermissionDialogFragment
|
||||||
|
import com.all.pdfreader.pro.app.ui.dialog.SortDialogFragment
|
||||||
import com.all.pdfreader.pro.app.ui.fragment.FavoriteFrag
|
import com.all.pdfreader.pro.app.ui.fragment.FavoriteFrag
|
||||||
import com.all.pdfreader.pro.app.ui.fragment.HomeFrag
|
import com.all.pdfreader.pro.app.ui.fragment.HomeFrag
|
||||||
import com.all.pdfreader.pro.app.ui.fragment.RecentlyFrag
|
import com.all.pdfreader.pro.app.ui.fragment.RecentlyFrag
|
||||||
import com.all.pdfreader.pro.app.ui.fragment.ToolsFrag
|
import com.all.pdfreader.pro.app.ui.fragment.ToolsFrag
|
||||||
import com.all.pdfreader.pro.app.model.SortConfig
|
|
||||||
import com.all.pdfreader.pro.app.model.SortField
|
|
||||||
import com.all.pdfreader.pro.app.model.SortDirection
|
|
||||||
import com.all.pdfreader.pro.app.ui.dialog.SortDialogFragment
|
|
||||||
import com.all.pdfreader.pro.app.util.AppUtils.setClickWithAnimation
|
import com.all.pdfreader.pro.app.util.AppUtils.setClickWithAnimation
|
||||||
import com.all.pdfreader.pro.app.util.FileChangeObserver
|
|
||||||
import com.all.pdfreader.pro.app.util.PdfScanner
|
import com.all.pdfreader.pro.app.util.PdfScanner
|
||||||
import com.all.pdfreader.pro.app.util.StoragePermissionHelper
|
import com.all.pdfreader.pro.app.util.StoragePermissionHelper
|
||||||
import com.gyf.immersionbar.ImmersionBar
|
import com.gyf.immersionbar.ImmersionBar
|
||||||
|
|||||||
@ -123,7 +123,7 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
|
|||||||
private fun saveReadingProgress() {
|
private fun saveReadingProgress() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
repository.updateReadingProgress(
|
repository.updateReadingProgress(
|
||||||
pdfDocument.fileHash, pdfDocument.lastReadPage, pdfDocument.readingProgress
|
pdfDocument.filePath, pdfDocument.lastReadPage, pdfDocument.readingProgress
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,128 @@
|
|||||||
|
package com.all.pdfreader.pro.app.ui.dialog
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.all.pdfreader.pro.app.R
|
||||||
|
import com.all.pdfreader.pro.app.databinding.DialogListMoreBinding
|
||||||
|
import com.all.pdfreader.pro.app.databinding.DialogPermissionBinding
|
||||||
|
import com.all.pdfreader.pro.app.databinding.DialogSortBinding
|
||||||
|
import com.all.pdfreader.pro.app.model.SortConfig
|
||||||
|
import com.all.pdfreader.pro.app.model.SortDirection
|
||||||
|
import com.all.pdfreader.pro.app.model.SortField
|
||||||
|
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
||||||
|
import com.all.pdfreader.pro.app.room.repository.PdfRepository
|
||||||
|
import com.all.pdfreader.pro.app.sp.AppStore
|
||||||
|
import com.all.pdfreader.pro.app.ui.act.MainActivity.SortableFragment
|
||||||
|
import com.all.pdfreader.pro.app.util.AppUtils.dpToPx
|
||||||
|
import com.all.pdfreader.pro.app.util.AppUtils.setClickWithAnimation
|
||||||
|
import com.all.pdfreader.pro.app.util.FileUtils.toFormatFileSize
|
||||||
|
import com.all.pdfreader.pro.app.util.FileUtils.toSlashDate
|
||||||
|
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment() {
|
||||||
|
|
||||||
|
private lateinit var binding: DialogListMoreBinding
|
||||||
|
private val pdfRepository = PdfRepository.getInstance()
|
||||||
|
private val viewModel by lazy { ViewModelProvider(this)[PdfViewModel::class.java] }
|
||||||
|
private lateinit var pdfDocument: PdfDocumentEntity
|
||||||
|
private var isFavorite: Boolean = false
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
binding = DialogListMoreBinding.inflate(layoutInflater)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
dialog?.window?.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
|
||||||
|
?.setBackgroundResource(R.drawable.dr_rounded_corner_12_bg_white)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
viewModel.pdfDocument.observe(this) { document ->
|
||||||
|
document?.let {
|
||||||
|
pdfDocument = it
|
||||||
|
isFavorite = pdfDocument.isFavorite
|
||||||
|
initUi()
|
||||||
|
setupOnClick()
|
||||||
|
|
||||||
|
} ?: run {
|
||||||
|
showToast(getString(R.string.file_not))
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewModel.getPDFDocument(filePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initUi() {
|
||||||
|
binding.tvFileName.text = pdfDocument.fileName
|
||||||
|
binding.tvFileSize.text = pdfDocument.fileSize.toFormatFileSize()
|
||||||
|
binding.tvFileDate.text = pdfDocument.lastModified.toSlashDate()
|
||||||
|
if (pdfDocument.isPassword) {
|
||||||
|
binding.lockLayout.visibility = View.VISIBLE
|
||||||
|
binding.tvFileImg.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
binding.lockLayout.visibility = View.GONE
|
||||||
|
binding.tvFileImg.visibility = View.VISIBLE
|
||||||
|
Glide.with(binding.root).load(pdfDocument.thumbnailPath)
|
||||||
|
.transform(CenterCrop(), RoundedCorners(8.dpToPx(binding.root.context)))
|
||||||
|
.into(binding.tvFileImg)
|
||||||
|
}
|
||||||
|
updateCollectUi(isFavorite)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupOnClick() {
|
||||||
|
binding.collectBtn.setClickWithAnimation(duration = 250) {
|
||||||
|
isFavorite = !isFavorite
|
||||||
|
updateCollectUi(isFavorite)
|
||||||
|
saveCollectState(isFavorite)
|
||||||
|
}
|
||||||
|
binding.renameFileBtn.setOnClickListener {
|
||||||
|
RenameDialogFragment(pdfDocument.filePath, onOkClick = {
|
||||||
|
|
||||||
|
}, onCancelClick = {
|
||||||
|
|
||||||
|
}).show(parentFragmentManager, "ListMoreDialogFragment")
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveCollectState(b: Boolean) {
|
||||||
|
pdfDocument = pdfDocument.copy(
|
||||||
|
isFavorite = b
|
||||||
|
)
|
||||||
|
lifecycleScope.launch {
|
||||||
|
pdfRepository.updateFavoriteStatus(pdfDocument.filePath, pdfDocument.isFavorite)
|
||||||
|
}
|
||||||
|
if (b) {
|
||||||
|
showToast(getString(R.string.added_to_favorites))
|
||||||
|
} else {
|
||||||
|
showToast(getString(R.string.removed_from_favorites))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateCollectUi(b: Boolean) {
|
||||||
|
if (b) {
|
||||||
|
binding.collectIv.setImageResource(R.drawable.collected)
|
||||||
|
} else {
|
||||||
|
binding.collectIv.setImageResource(R.drawable.collect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showToast(message: String) {
|
||||||
|
Toast.makeText(requireActivity(), message, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@ package com.all.pdfreader.pro.app.ui.dialog
|
|||||||
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.InputType
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -21,7 +20,6 @@ class PdfPasswordProtectionDialogFragment(
|
|||||||
) : DialogFragment() {
|
) : DialogFragment() {
|
||||||
|
|
||||||
private lateinit var binding: DialogPdfPasswordProtectionBinding
|
private lateinit var binding: DialogPdfPasswordProtectionBinding
|
||||||
var isPasswordVisible = false
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
@ -67,23 +65,5 @@ class PdfPasswordProtectionDialogFragment(
|
|||||||
binding.tilPassword.error = getString(R.string.incorrect_password)
|
binding.tilPassword.error = getString(R.string.incorrect_password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.showPasswordBtn.setOnClickListener {
|
|
||||||
isPasswordVisible = !isPasswordVisible
|
|
||||||
showOrHidePassword(isPasswordVisible)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showOrHidePassword(b: Boolean) {
|
|
||||||
if (b) {
|
|
||||||
binding.etPassword.inputType =
|
|
||||||
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|
|
||||||
binding.showPasswordIv.setImageResource(R.drawable.show_password)
|
|
||||||
} else {
|
|
||||||
binding.etPassword.inputType =
|
|
||||||
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
|
|
||||||
binding.showPasswordIv.setImageResource(R.drawable.hide_password)
|
|
||||||
}
|
|
||||||
// 保持光标在末尾
|
|
||||||
binding.etPassword.setSelection(binding.etPassword.text?.length ?: 0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,18 +3,15 @@ package com.all.pdfreader.pro.app.ui.dialog
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.InputType
|
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.core.graphics.drawable.toDrawable
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import com.all.pdfreader.pro.app.R
|
import com.all.pdfreader.pro.app.R
|
||||||
import com.all.pdfreader.pro.app.databinding.DialogPdfSetPasswordBinding
|
import com.all.pdfreader.pro.app.databinding.DialogPdfSetPasswordBinding
|
||||||
import com.all.pdfreader.pro.app.util.AppUtils.showKeyboard
|
import com.all.pdfreader.pro.app.util.AppUtils.showKeyboard
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
|
||||||
|
|
||||||
class PdfSetPasswordDialog(
|
class PdfSetPasswordDialog(
|
||||||
private val onCancelled: () -> Unit, private val onPasswordSet: (String) -> Unit
|
private val onCancelled: () -> Unit, private val onPasswordSet: (String) -> Unit
|
||||||
@ -22,8 +19,6 @@ class PdfSetPasswordDialog(
|
|||||||
|
|
||||||
) {
|
) {
|
||||||
private lateinit var binding: DialogPdfSetPasswordBinding
|
private lateinit var binding: DialogPdfSetPasswordBinding
|
||||||
private var isEnterPasswordVisible = false
|
|
||||||
private var isConfirmPasswordVisible = false
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
@ -66,23 +61,6 @@ class PdfSetPasswordDialog(
|
|||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.enterShowPasswordBtn.setOnClickListener {
|
|
||||||
isEnterPasswordVisible = !isEnterPasswordVisible
|
|
||||||
showOrHidePassword(
|
|
||||||
binding.etPassword,
|
|
||||||
binding.enterShowPasswordIv,
|
|
||||||
isEnterPasswordVisible
|
|
||||||
)
|
|
||||||
}
|
|
||||||
binding.confirmShowPasswordBtn.setOnClickListener {
|
|
||||||
isConfirmPasswordVisible = !isConfirmPasswordVisible
|
|
||||||
showOrHidePassword(
|
|
||||||
binding.etConfirmPassword,
|
|
||||||
binding.confirmShowPasswordIv,
|
|
||||||
isConfirmPasswordVisible
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupTextWatchers() {
|
private fun setupTextWatchers() {
|
||||||
@ -140,17 +118,4 @@ class PdfSetPasswordDialog(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showOrHidePassword(inputView: TextInputEditText, imageView: ImageView, b: Boolean) {
|
|
||||||
if (b) {
|
|
||||||
inputView.inputType =
|
|
||||||
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|
|
||||||
imageView.setImageResource(R.drawable.show_password)
|
|
||||||
} else {
|
|
||||||
inputView.inputType =
|
|
||||||
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
|
|
||||||
imageView.setImageResource(R.drawable.hide_password)
|
|
||||||
}
|
|
||||||
// 保持光标在末尾
|
|
||||||
inputView.setSelection(inputView.text?.length ?: 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,135 @@
|
|||||||
|
package com.all.pdfreader.pro.app.ui.dialog
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.InputType
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.all.pdfreader.pro.app.R
|
||||||
|
import com.all.pdfreader.pro.app.databinding.DialogPdfPasswordProtectionBinding
|
||||||
|
import com.all.pdfreader.pro.app.databinding.DialogRenameFileBinding
|
||||||
|
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
||||||
|
import com.all.pdfreader.pro.app.util.AppUtils.showKeyboard
|
||||||
|
import com.all.pdfreader.pro.app.util.FileUtils.isPdfPasswordCorrect
|
||||||
|
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class RenameDialogFragment(
|
||||||
|
private val filePath: String,
|
||||||
|
private val onOkClick: () -> Unit,
|
||||||
|
private val onCancelClick: () -> Unit
|
||||||
|
) : DialogFragment() {
|
||||||
|
|
||||||
|
private lateinit var binding: DialogRenameFileBinding
|
||||||
|
private val viewModel by lazy { ViewModelProvider(this)[PdfViewModel::class.java] }
|
||||||
|
private lateinit var pdfDocument: PdfDocumentEntity
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
binding = DialogRenameFileBinding.inflate(layoutInflater)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
dialog?.window?.apply {
|
||||||
|
// 去掉系统默认的背景 padding
|
||||||
|
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
|
||||||
|
// 设置宽度为全屏减去 16dp
|
||||||
|
val margin = resources.getDimensionPixelSize(R.dimen.dialog_margin) // 16dp
|
||||||
|
val width = resources.displayMetrics.widthPixels - margin * 2
|
||||||
|
setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
viewModel.pdfDocument.observe(this) { document ->
|
||||||
|
document?.let {
|
||||||
|
pdfDocument = it
|
||||||
|
initView()
|
||||||
|
setupOnClick()
|
||||||
|
} ?: run {
|
||||||
|
showToast(getString(R.string.file_not))
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewModel.getPDFDocument(filePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initView() {
|
||||||
|
binding.etName.showKeyboard()
|
||||||
|
binding.etName.setText(pdfDocument.fileName)
|
||||||
|
// 保持光标在末尾
|
||||||
|
binding.etName.setSelection(binding.etName.text?.length ?: 0)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupOnClick() {
|
||||||
|
binding.tvCancel.setOnClickListener {
|
||||||
|
onCancelClick()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
binding.tvConfirm.setOnClickListener {
|
||||||
|
val text = binding.etName.text.toString()
|
||||||
|
if (validateEnter(text)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateEnter(name: String): Boolean {
|
||||||
|
// 不允许为空
|
||||||
|
if (name.isBlank()) {
|
||||||
|
binding.tilName.error = getString(R.string.name_not_empty)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 名字未做修改
|
||||||
|
if (name == pdfDocument.fileName) {
|
||||||
|
binding.tilName.error = getString(R.string.name_not_changed)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 含有非法字符
|
||||||
|
val invalidChars = "[/\\\\:*?\"<>|]".toRegex()
|
||||||
|
if (invalidChars.containsMatchIn(name)) {
|
||||||
|
binding.tilName.error = getString(R.string.name_invalid_chars)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 长度过长
|
||||||
|
if (name.length > 255) {
|
||||||
|
binding.tilName.error = getString(R.string.name_too_long)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 与现有文件重名
|
||||||
|
val parentDir = File(pdfDocument.filePath).parentFile
|
||||||
|
if (parentDir != null && File(parentDir, name).exists()) {
|
||||||
|
binding.tilName.error = getString(R.string.name_already_exists)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 禁止开头/结尾空格
|
||||||
|
if (name != name.trim()) {
|
||||||
|
binding.tilName.error = getString(R.string.name_start_end_space)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun showToast(message: String) {
|
||||||
|
Toast.makeText(requireActivity(), message, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import com.all.pdfreader.pro.app.R
|
||||||
import com.all.pdfreader.pro.app.databinding.DialogPermissionBinding
|
import com.all.pdfreader.pro.app.databinding.DialogPermissionBinding
|
||||||
import com.all.pdfreader.pro.app.databinding.DialogSortBinding
|
import com.all.pdfreader.pro.app.databinding.DialogSortBinding
|
||||||
import com.all.pdfreader.pro.app.model.SortConfig
|
import com.all.pdfreader.pro.app.model.SortConfig
|
||||||
@ -30,6 +31,12 @@ class SortDialogFragment(
|
|||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
dialog?.window?.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
|
||||||
|
?.setBackgroundResource(R.drawable.dr_rounded_corner_12_bg_white)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
val appStore = AppStore(requireActivity())
|
val appStore = AppStore(requireActivity())
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import com.all.pdfreader.pro.app.room.repository.PdfRepository
|
|||||||
import com.all.pdfreader.pro.app.ui.act.MainActivity
|
import com.all.pdfreader.pro.app.ui.act.MainActivity
|
||||||
import com.all.pdfreader.pro.app.ui.act.PdfViewActivity
|
import com.all.pdfreader.pro.app.ui.act.PdfViewActivity
|
||||||
import com.all.pdfreader.pro.app.ui.adapter.PdfAdapter
|
import com.all.pdfreader.pro.app.ui.adapter.PdfAdapter
|
||||||
|
import com.all.pdfreader.pro.app.ui.dialog.ListMoreDialogFragment
|
||||||
import com.all.pdfreader.pro.app.util.PdfScanner
|
import com.all.pdfreader.pro.app.util.PdfScanner
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ class HomeFrag : BaseFrag(), MainActivity.SortableFragment {
|
|||||||
val intent = PdfViewActivity.createIntent(requireContext(), pdf.filePath)
|
val intent = PdfViewActivity.createIntent(requireContext(), pdf.filePath)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}, onMoreClick = { pdf ->
|
}, onMoreClick = { pdf ->
|
||||||
|
ListMoreDialogFragment(pdf.filePath).show(parentFragmentManager, TAG)
|
||||||
})
|
})
|
||||||
|
|
||||||
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||||
|
|||||||
@ -14,7 +14,11 @@ object AppUtils {
|
|||||||
*
|
*
|
||||||
* @param onClick 点击后立即执行的逻辑
|
* @param onClick 点击后立即执行的逻辑
|
||||||
*/
|
*/
|
||||||
fun View.setClickWithAnimation(onClick: () -> Unit) {
|
fun View.setClickWithAnimation(
|
||||||
|
scaleFactor: Float = 1.2f,
|
||||||
|
duration: Long = 150,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
this.setOnClickListener {
|
this.setOnClickListener {
|
||||||
// 禁用点击,防止动画未完成重复点击
|
// 禁用点击,防止动画未完成重复点击
|
||||||
this.isEnabled = false
|
this.isEnabled = false
|
||||||
@ -24,14 +28,14 @@ object AppUtils {
|
|||||||
|
|
||||||
// 播放动画
|
// 播放动画
|
||||||
this.animate()
|
this.animate()
|
||||||
.scaleX(1.2f)
|
.scaleX(scaleFactor)
|
||||||
.scaleY(1.2f)
|
.scaleY(scaleFactor)
|
||||||
.setDuration(150)
|
.setDuration(duration)
|
||||||
.withEndAction {
|
.withEndAction {
|
||||||
this.animate()
|
this.animate()
|
||||||
.scaleX(1f)
|
.scaleX(1f)
|
||||||
.scaleY(1f)
|
.scaleY(1f)
|
||||||
.setDuration(150)
|
.setDuration(duration)
|
||||||
.withEndAction {
|
.withEndAction {
|
||||||
// 动画结束恢复点击
|
// 动画结束恢复点击
|
||||||
this.isEnabled = true
|
this.isEnabled = true
|
||||||
|
|||||||
@ -237,6 +237,9 @@ object FileUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算文件哈希
|
||||||
|
*/
|
||||||
fun calculateFileHash(filePath: String): String? {
|
fun calculateFileHash(filePath: String): String? {
|
||||||
return try {
|
return try {
|
||||||
val file = File(filePath)
|
val file = File(filePath)
|
||||||
|
|||||||
@ -2,9 +2,7 @@ package com.all.pdfreader.pro.app.util
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.pdf.PdfRenderer
|
|
||||||
import android.os.ParcelFileDescriptor
|
import android.os.ParcelFileDescriptor
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.graphics.createBitmap
|
import androidx.core.graphics.createBitmap
|
||||||
@ -12,7 +10,10 @@ import com.all.pdfreader.pro.app.PDFReaderApplication
|
|||||||
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
||||||
import com.all.pdfreader.pro.app.room.repository.PdfRepository
|
import com.all.pdfreader.pro.app.room.repository.PdfRepository
|
||||||
import com.all.pdfreader.pro.app.util.FileUtils.isPdfEncrypted
|
import com.all.pdfreader.pro.app.util.FileUtils.isPdfEncrypted
|
||||||
|
import com.shockwave.pdfium.PdfDocument
|
||||||
|
import com.shockwave.pdfium.PdfiumCore
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -29,7 +30,9 @@ class PdfScanner(
|
|||||||
suspend fun scanAndLoadPdfFiles(isNeedFullScan: Boolean, callback: (Boolean) -> Unit = {}) {
|
suspend fun scanAndLoadPdfFiles(isNeedFullScan: Boolean, callback: (Boolean) -> Unit = {}) {
|
||||||
if (!StoragePermissionHelper.hasBasicStoragePermission(context)) {
|
if (!StoragePermissionHelper.hasBasicStoragePermission(context)) {
|
||||||
LogUtil.logDebug(TAG, "权限不足")
|
LogUtil.logDebug(TAG, "权限不足")
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
callback.invoke(false)
|
callback.invoke(false)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
scanMutex.withLock {// 保证同一时间只有一次扫描
|
scanMutex.withLock {// 保证同一时间只有一次扫描
|
||||||
@ -64,23 +67,30 @@ class PdfScanner(
|
|||||||
LogUtil.logDebug(TAG, "密码状态变化 -> ${doc.fileName}")
|
LogUtil.logDebug(TAG, "密码状态变化 -> ${doc.fileName}")
|
||||||
updatedDoc = updatedDoc.copy(isPassword = currentIsPassword)
|
updatedDoc = updatedDoc.copy(isPassword = currentIsPassword)
|
||||||
}
|
}
|
||||||
// 缩略图(仅非加密文件)
|
|
||||||
if (!currentIsPassword) {
|
|
||||||
val newThumbnail = generateThumbnail(context, file)
|
|
||||||
if (doc.thumbnailPath != newThumbnail) {
|
|
||||||
updatedDoc =
|
|
||||||
updatedDoc.copy(thumbnailPath = newThumbnail)
|
|
||||||
}
|
|
||||||
} else if (doc.thumbnailPath != null) {
|
|
||||||
updatedDoc = updatedDoc.copy(thumbnailPath = null)
|
|
||||||
}
|
|
||||||
pdfRepository.insertOrUpdateDocument(updatedDoc)
|
pdfRepository.insertOrUpdateDocument(updatedDoc)
|
||||||
LogUtil.logDebug(TAG, "✅数据库已更新: ${doc.fileName}")
|
LogUtil.logDebug(TAG, "✅数据库已更新: ${doc.fileName}")
|
||||||
|
|
||||||
|
if (!currentIsPassword) {
|
||||||
|
// 异步生成缩略图,但要避免阻塞
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
LogUtil.logDebug(TAG, "异步获取图片更新数据")
|
||||||
|
val newThumbnail = generateFastThumbnail(context, file)
|
||||||
|
if (newThumbnail != null && doc.thumbnailPath != newThumbnail) {
|
||||||
|
pdfRepository.updateThumbnailPath(doc.filePath, newThumbnail)
|
||||||
|
LogUtil.logDebug(TAG, "✅ 缩略图已更新")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (doc.thumbnailPath != null) {
|
||||||
|
val updatedDocWithoutThumb =
|
||||||
|
updatedDoc.copy(thumbnailPath = null)
|
||||||
|
pdfRepository.insertOrUpdateDocument(updatedDocWithoutThumb)
|
||||||
|
LogUtil.logDebug(TAG, "✅图片为Null: ${doc.fileName}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 文件不存在 → 删除数据库记录,并触发全盘扫描
|
// 文件不存在 → 删除数据库记录,并触发全盘扫描
|
||||||
LogUtil.logDebug(TAG, "文件不存在 -> ${doc.fileName}, 删除记录")
|
LogUtil.logDebug(TAG, "文件不存在 -> ${doc.fileName}, 删除记录")
|
||||||
pdfRepository.deleteDocument(doc.fileHash)
|
pdfRepository.deleteDocument(doc.filePath)
|
||||||
needFullScan = true
|
needFullScan = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,12 +113,7 @@ class PdfScanner(
|
|||||||
TAG,
|
TAG,
|
||||||
"🔄处理文件 ${index + 1}/${allFiles.size}: ${file.name} - ${file.absolutePath}"
|
"🔄处理文件 ${index + 1}/${allFiles.size}: ${file.name} - ${file.absolutePath}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (FileUtils.isPdfFile(file)) {
|
if (FileUtils.isPdfFile(file)) {
|
||||||
val fileHash = FileUtils.calculateFileHash(file.absolutePath)
|
|
||||||
LogUtil.logDebug(TAG, "🔑文件哈希: $fileHash")
|
|
||||||
|
|
||||||
if (fileHash != null) {
|
|
||||||
val existingDoc =
|
val existingDoc =
|
||||||
pdfRepository.getDocumentByPath(file.absolutePath)
|
pdfRepository.getDocumentByPath(file.absolutePath)
|
||||||
|
|
||||||
@ -116,23 +121,18 @@ class PdfScanner(
|
|||||||
LogUtil.logDebug(
|
LogUtil.logDebug(
|
||||||
TAG, "🆕发现新PDF文件: ${file.name}"
|
TAG, "🆕发现新PDF文件: ${file.name}"
|
||||||
)
|
)
|
||||||
var thumbnailPath: String? = null
|
|
||||||
val isPassword = isPdfEncrypted(file)
|
val isPassword = isPdfEncrypted(file)
|
||||||
LogUtil.logDebug(TAG, "isPassword->${isPassword}")
|
LogUtil.logDebug(TAG, "isPassword->${isPassword}")
|
||||||
if (!isPassword) {//没有密码的情况下才去获取缩略图
|
|
||||||
thumbnailPath = generateThumbnail(context, file) ?: ""
|
|
||||||
}
|
|
||||||
LogUtil.logDebug(TAG, "thumbnailPath->${thumbnailPath}")
|
|
||||||
val metadata =
|
val metadata =
|
||||||
PdfMetadataExtractor.extractMetadata(file.absolutePath)
|
PdfMetadataExtractor.extractMetadata(file.absolutePath)
|
||||||
val document = PdfDocumentEntity(
|
val document = PdfDocumentEntity(
|
||||||
fileHash = fileHash,
|
|
||||||
filePath = file.absolutePath,
|
filePath = file.absolutePath,
|
||||||
fileName = file.name,
|
fileName = file.name,
|
||||||
fileSize = file.length(),
|
fileSize = file.length(),
|
||||||
lastModified = file.lastModified(),
|
lastModified = file.lastModified(),
|
||||||
pageCount = metadata?.pageCount ?: 0,
|
pageCount = metadata?.pageCount ?: 0,
|
||||||
thumbnailPath = thumbnailPath,
|
thumbnailPath = null,
|
||||||
metadataTitle = metadata?.title,
|
metadataTitle = metadata?.title,
|
||||||
metadataAuthor = metadata?.author,
|
metadataAuthor = metadata?.author,
|
||||||
metadataSubject = metadata?.subject,
|
metadataSubject = metadata?.subject,
|
||||||
@ -142,9 +142,17 @@ class PdfScanner(
|
|||||||
isPassword = isPassword
|
isPassword = isPassword
|
||||||
)
|
)
|
||||||
pdfRepository.insertOrUpdateDocument(document)
|
pdfRepository.insertOrUpdateDocument(document)
|
||||||
LogUtil.logDebug(
|
LogUtil.logDebug(TAG, " ✅ 已保存到数据库: ${file.name}")
|
||||||
TAG, " ✅ 已保存到数据库: ${file.name}"
|
|
||||||
)
|
if (!isPassword) {//没有密码的情况下才去获取缩略图
|
||||||
|
launch(Dispatchers.IO){
|
||||||
|
val newThumbnail = generateFastThumbnail(context, file)
|
||||||
|
if (newThumbnail != null && document.thumbnailPath != newThumbnail) {
|
||||||
|
pdfRepository.updateThumbnailPath(document.filePath, newThumbnail)
|
||||||
|
LogUtil.logDebug(TAG, "✅ 缩略图已更新")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LogUtil.logDebug(TAG, " 📋 文件已存在: ${file.name}")
|
LogUtil.logDebug(TAG, " 📋 文件已存在: ${file.name}")
|
||||||
// 🔹 文件已存在,检查是否需要更新
|
// 🔹 文件已存在,检查是否需要更新
|
||||||
@ -170,31 +178,27 @@ class PdfScanner(
|
|||||||
needUpdate = true
|
needUpdate = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentIsPassword) {
|
|
||||||
// 如果不是加密 PDF,再生成缩略图
|
|
||||||
val newThumbnail = generateThumbnail(context, file)
|
|
||||||
if (existingDoc.thumbnailPath != newThumbnail) {
|
|
||||||
LogUtil.logDebug(TAG, "✅ 缩略图需要更新")
|
|
||||||
updatedDoc =
|
|
||||||
updatedDoc.copy(thumbnailPath = newThumbnail)
|
|
||||||
needUpdate = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
updatedDoc = updatedDoc.copy(thumbnailPath = null)
|
|
||||||
needUpdate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行更新
|
// 执行更新
|
||||||
if (needUpdate) {
|
if (needUpdate) {
|
||||||
pdfRepository.insertOrUpdateDocument(updatedDoc)
|
pdfRepository.insertOrUpdateDocument(updatedDoc)
|
||||||
LogUtil.logDebug(
|
LogUtil.logDebug(TAG, "✅ 数据库已更新: ${file.name}")
|
||||||
TAG, "✅ 数据库已更新: ${file.name}"
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
LogUtil.logDebug(
|
LogUtil.logDebug(TAG, "⏩ 无需更新: ${file.name}")
|
||||||
TAG, "⏩ 无需更新: ${file.name}"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理缩略图
|
||||||
|
if (!currentIsPassword) {
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
LogUtil.logDebug(TAG, "异步获取图片更新数据")
|
||||||
|
val newThumbnail = generateFastThumbnail(context, file)
|
||||||
|
if (newThumbnail != null && existingDoc.thumbnailPath != newThumbnail) {
|
||||||
|
pdfRepository.updateThumbnailPath(existingDoc.filePath, newThumbnail)
|
||||||
|
LogUtil.logDebug(TAG, "✅ 缩略图已更新")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val noThumbDoc = updatedDoc.copy(thumbnailPath = null)
|
||||||
|
pdfRepository.insertOrUpdateDocument(noThumbDoc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,7 +206,8 @@ class PdfScanner(
|
|||||||
// 打印数据库中的总记录数
|
// 打印数据库中的总记录数
|
||||||
pdfRepository.getAllDocumentsOnce().forEach { doc ->
|
pdfRepository.getAllDocumentsOnce().forEach { doc ->
|
||||||
LogUtil.logDebug(
|
LogUtil.logDebug(
|
||||||
TAG, " 📖 ${doc.fileName} - ${doc.pageCount}页 - ${
|
TAG,
|
||||||
|
" 📖 ${doc.fileName} - ${doc.filePath} - ${doc.pageCount}页 - ${
|
||||||
FileUtils.formatFileSize(
|
FileUtils.formatFileSize(
|
||||||
doc.fileSize
|
doc.fileSize
|
||||||
)
|
)
|
||||||
@ -229,14 +234,18 @@ class PdfScanner(
|
|||||||
TAG, "$string 本次扫描耗时: $scannerTime ms (${scannerTime / 1000.0} 秒)"
|
TAG, "$string 本次扫描耗时: $scannerTime ms (${scannerTime / 1000.0} 秒)"
|
||||||
)
|
)
|
||||||
PDFReaderApplication.isNeedFullScan = false
|
PDFReaderApplication.isNeedFullScan = false
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
callback.invoke(true)
|
callback.invoke(true)
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "❌ 扫描出错: ${e.message}", e)
|
Log.e(TAG, "❌ 扫描出错: ${e.message}", e)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
callback.invoke(false)
|
callback.invoke(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun shouldScan(): Boolean {
|
fun shouldScan(): Boolean {
|
||||||
return ScanManager.shouldScan(context)
|
return ScanManager.shouldScan(context)
|
||||||
@ -252,40 +261,87 @@ class PdfScanner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun generateThumbnail(context: Context, pdfFile: File): String? {
|
// private fun generateFastThumbnail(context: Context, pdfFile: File): String? {
|
||||||
|
// return try {
|
||||||
|
// val fileDescriptor =
|
||||||
|
// ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY)
|
||||||
|
// val pdfRenderer = PdfRenderer(fileDescriptor)
|
||||||
|
//
|
||||||
|
// if (pdfRenderer.pageCount > 0) {
|
||||||
|
// val page = pdfRenderer.openPage(0)
|
||||||
|
// // 创建 Bitmap
|
||||||
|
// val bitmap = createBitmap(page.width, page.height)
|
||||||
|
// val canvas = Canvas(bitmap)
|
||||||
|
// canvas.drawColor(Color.WHITE) // 填充白色背景
|
||||||
|
//
|
||||||
|
// page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
|
||||||
|
// page.close()
|
||||||
|
//
|
||||||
|
// // 保存到缓存目录
|
||||||
|
// val cacheDir = File(context.cacheDir, "thumbnails")
|
||||||
|
// if (!cacheDir.exists()) cacheDir.mkdirs()
|
||||||
|
// val thumbFile = File(cacheDir, pdfFile.nameWithoutExtension + ".jpg")
|
||||||
|
//
|
||||||
|
// FileOutputStream(thumbFile).use { out ->
|
||||||
|
// bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// pdfRenderer.close()
|
||||||
|
// fileDescriptor.close()
|
||||||
|
//
|
||||||
|
// thumbFile.absolutePath
|
||||||
|
// } else {
|
||||||
|
// pdfRenderer.close()
|
||||||
|
// fileDescriptor.close()
|
||||||
|
// null
|
||||||
|
// }
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// e.printStackTrace()
|
||||||
|
// null
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
private fun generateFastThumbnail(
|
||||||
|
context: Context,
|
||||||
|
pdfFile: File,
|
||||||
|
maxWidth: Int = 200,
|
||||||
|
maxHeight: Int = 300
|
||||||
|
): String? {
|
||||||
return try {
|
return try {
|
||||||
val fileDescriptor =
|
val pdfiumCore = PdfiumCore(context)
|
||||||
ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY)
|
val fd = ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY)
|
||||||
val pdfRenderer = PdfRenderer(fileDescriptor)
|
val pdfDocument: PdfDocument = pdfiumCore.newDocument(fd)
|
||||||
|
|
||||||
if (pdfRenderer.pageCount > 0) {
|
// 打开第一页
|
||||||
val page = pdfRenderer.openPage(0)
|
pdfiumCore.openPage(pdfDocument, 0)
|
||||||
// 创建 Bitmap
|
|
||||||
val bitmap = createBitmap(page.width, page.height)
|
|
||||||
val canvas = Canvas(bitmap)
|
|
||||||
canvas.drawColor(Color.WHITE) // 填充白色背景
|
|
||||||
|
|
||||||
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
|
// 获取原始页宽高
|
||||||
page.close()
|
val width = pdfiumCore.getPageWidthPoint(pdfDocument, 0)
|
||||||
|
val height = pdfiumCore.getPageHeightPoint(pdfDocument, 0)
|
||||||
|
|
||||||
// 保存到缓存目录
|
// 计算缩略图尺寸
|
||||||
|
val scale = minOf(maxWidth.toFloat() / width, maxHeight.toFloat() / height)
|
||||||
|
val thumbWidth = (width * scale).toInt()
|
||||||
|
val thumbHeight = (height * scale).toInt()
|
||||||
|
|
||||||
|
val bitmap = createBitmap(thumbWidth, thumbHeight)
|
||||||
|
bitmap.eraseColor(Color.WHITE) // 白底
|
||||||
|
|
||||||
|
// 渲染第一页到 Bitmap
|
||||||
|
pdfiumCore.renderPageBitmap(pdfDocument, bitmap, 0, 0, 0, thumbWidth, thumbHeight)
|
||||||
|
|
||||||
|
// 保存到缓存
|
||||||
val cacheDir = File(context.cacheDir, "thumbnails")
|
val cacheDir = File(context.cacheDir, "thumbnails")
|
||||||
if (!cacheDir.exists()) cacheDir.mkdirs()
|
if (!cacheDir.exists()) cacheDir.mkdirs()
|
||||||
val thumbFile = File(cacheDir, pdfFile.nameWithoutExtension + ".jpg")
|
val thumbFile = File(cacheDir, pdfFile.nameWithoutExtension + ".jpg")
|
||||||
|
|
||||||
FileOutputStream(thumbFile).use { out ->
|
FileOutputStream(thumbFile).use { out ->
|
||||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out)
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
pdfRenderer.close()
|
pdfiumCore.closeDocument(pdfDocument)
|
||||||
fileDescriptor.close()
|
fd.close()
|
||||||
|
|
||||||
thumbFile.absolutePath
|
thumbFile.absolutePath
|
||||||
} else {
|
|
||||||
pdfRenderer.close()
|
|
||||||
fileDescriptor.close()
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
null
|
null
|
||||||
|
|||||||
9
app/src/main/res/drawable/collect.xml
Normal file
9
app/src/main/res/drawable/collect.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="256dp"
|
||||||
|
android:height="256dp"
|
||||||
|
android:viewportWidth="1024"
|
||||||
|
android:viewportHeight="1024">
|
||||||
|
<path
|
||||||
|
android:pathData="M859.7,253.9c-44.8,-44.8 -102.4,-70.4 -166.4,-70.4 -61.9,0 -121.6,25.6 -166.4,70.4l-14.9,17.1 -17.1,-17.1c-44.8,-44.8 -102.4,-70.4 -166.4,-70.4 -61.9,0 -121.6,25.6 -166.4,70.4 -91.7,91.7 -91.7,243.2 0,337.1l324.3,330.7c6.4,6.4 14.9,8.5 23.5,8.5s17.1,-4.3 23.5,-8.5l324.3,-330.7c44.8,-44.8 68.3,-104.5 68.3,-168.5s-21.3,-123.7 -66.1,-168.5zM814.9,544L512,853.3 209.1,544c-66.1,-68.3 -66.1,-179.2 0,-247.5 32,-32 74.7,-51.2 119.5,-51.2 44.8,0 87.5,17.1 119.5,51.2l38.4,40.5c12.8,12.8 34.1,12.8 44.8,0l38.4,-40.5c32,-32 74.7,-51.2 119.5,-51.2 44.8,0 87.5,17.1 119.5,51.2 32,32 49.1,76.8 49.1,123.7s-12.8,91.7 -42.7,123.7z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
</vector>
|
||||||
9
app/src/main/res/drawable/collected.xml
Normal file
9
app/src/main/res/drawable/collected.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="256dp"
|
||||||
|
android:height="256dp"
|
||||||
|
android:viewportWidth="1024"
|
||||||
|
android:viewportHeight="1024">
|
||||||
|
<path
|
||||||
|
android:pathData="M669.8,130.8c71.6,-11.1 138.9,11.5 193.3,64.5 55.3,53.9 81.8,125 74.3,199.5 -7.5,73.6 -46.5,146.4 -112.3,210.5 -18.3,17.9 -67.7,66.2 -138.5,135.6 -31.8,31.2 -65.7,64.4 -99.8,98L553.6,871.5l-13.2,12.9a40.6,40.6 0,0 1,-56.8 0l-114.6,-112.6 -24.2,-23.7a677626.4,677626.4 0,0 0,-145.9 -142.8C133.1,541.2 94.1,468.5 86.6,394.8c-7.6,-74.5 18.9,-145.6 74.3,-199.5 54.4,-53.1 121.7,-75.6 193.3,-64.5 53.2,8.2 107.1,34.7 157.8,76.9 50.7,-42.2 104.6,-68.7 157.8,-76.9z"
|
||||||
|
android:fillColor="#F1494F"/>
|
||||||
|
</vector>
|
||||||
12
app/src/main/res/drawable/delete.xml
Normal file
12
app/src/main/res/drawable/delete.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="1024"
|
||||||
|
android:viewportHeight="1024">
|
||||||
|
<path
|
||||||
|
android:pathData="M874.7,202.7L360.5,202.7c-21.3,0 -40.5,8.5 -55.5,23.5l-217.6,234.7c-25.6,27.7 -25.6,72.5 0,100.3l217.6,234.7c14.9,14.9 34.1,23.5 55.5,23.5L874.7,819.2c40.5,0 74.7,-34.1 74.7,-74.7L949.3,277.3c0,-40.5 -34.1,-74.7 -74.7,-74.7zM885.3,746.7c0,6.4 -4.3,10.7 -10.7,10.7L360.5,757.3c-2.1,0 -6.4,-2.1 -8.5,-4.3l-217.6,-234.7c-4.3,-4.3 -4.3,-10.7 0,-14.9l217.6,-234.7c2.1,-2.1 4.3,-4.3 8.5,-4.3L874.7,264.5c6.4,0 10.7,4.3 10.7,10.7L885.3,746.7z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M684.8,403.2c-12.8,-12.8 -32,-12.8 -44.8,0l-64,64 -61.9,-61.9c-12.8,-12.8 -32,-12.8 -44.8,0 -12.8,12.8 -12.8,32 0,44.8l61.9,61.9 -61.9,61.9c-12.8,12.8 -12.8,32 0,44.8 6.4,6.4 14.9,8.5 23.5,8.5s17.1,-2.1 23.5,-8.5l61.9,-61.9L640,618.7c6.4,6.4 14.9,8.5 23.5,8.5s17.1,-2.1 23.5,-8.5c12.8,-12.8 12.8,-32 0,-44.8L620.8,512l61.9,-61.9c12.8,-12.8 12.8,-34.1 2.1,-46.9z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
</vector>
|
||||||
10
app/src/main/res/drawable/dr_dialog_indicator_bg.xml
Normal file
10
app/src/main/res/drawable/dr_dialog_indicator_bg.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="4dp" />
|
||||||
|
<size
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="4dp" />
|
||||||
|
<solid android:color="@color/line_color" />
|
||||||
|
|
||||||
|
</shape>
|
||||||
5
app/src/main/res/drawable/dr_password_state.xml
Normal file
5
app/src/main/res/drawable/dr_password_state.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@drawable/show_password" android:state_checked="true"/>
|
||||||
|
<item android:drawable="@drawable/hide_password"/>
|
||||||
|
</selector>
|
||||||
12
app/src/main/res/drawable/duplicate.xml
Normal file
12
app/src/main/res/drawable/duplicate.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="256dp"
|
||||||
|
android:height="256dp"
|
||||||
|
android:viewportWidth="1024"
|
||||||
|
android:viewportHeight="1024">
|
||||||
|
<path
|
||||||
|
android:pathData="M853.3,224h-53.3L800,170.7c0,-40.5 -34.1,-74.7 -74.7,-74.7L170.7,96C130.1,96 96,130.1 96,170.7v554.7c0,40.5 34.1,74.7 74.7,74.7h53.3L224,853.3c0,40.5 34.1,74.7 74.7,74.7h554.7c40.5,0 74.7,-34.1 74.7,-74.7L928,298.7c0,-40.5 -34.1,-74.7 -74.7,-74.7zM160,725.3L160,170.7c0,-6.4 4.3,-10.7 10.7,-10.7h554.7c6.4,0 10.7,4.3 10.7,10.7v554.7c0,6.4 -4.3,10.7 -10.7,10.7L170.7,736c-6.4,0 -10.7,-4.3 -10.7,-10.7zM864,853.3c0,6.4 -4.3,10.7 -10.7,10.7L298.7,864c-6.4,0 -10.7,-4.3 -10.7,-10.7v-53.3L725.3,800c40.5,0 74.7,-34.1 74.7,-74.7L800,288L853.3,288c6.4,0 10.7,4.3 10.7,10.7v554.7z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M576,416h-96V320c0,-17.1 -14.9,-32 -32,-32s-32,14.9 -32,32v96H320c-17.1,0 -32,14.9 -32,32s14.9,32 32,32h96V576c0,17.1 14.9,32 32,32s32,-14.9 32,-32v-96H576c17.1,0 32,-14.9 32,-32s-14.9,-32 -32,-32z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
</vector>
|
||||||
12
app/src/main/res/drawable/file_delete.xml
Normal file
12
app/src/main/res/drawable/file_delete.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="256dp"
|
||||||
|
android:height="256dp"
|
||||||
|
android:viewportWidth="1024"
|
||||||
|
android:viewportHeight="1024">
|
||||||
|
<path
|
||||||
|
android:pathData="M842.7,285.9l-187.7,-187.7c-14.9,-14.9 -32,-21.3 -53.3,-21.3L234.7,76.8C194.1,74.7 160,108.8 160,149.3v725.3c0,40.5 34.1,74.7 74.7,74.7h554.7c40.5,0 74.7,-34.1 74.7,-74.7L864,337.1c0,-19.2 -8.5,-38.4 -21.3,-51.2zM797.9,330.7c-2.1,2.1 -4.3,0 -8.5,0h-170.7c-6.4,0 -10.7,-4.3 -10.7,-10.7L608,149.3c0,-2.1 0,-6.4 -2.1,-8.5 0,0 2.1,0 2.1,2.1l189.9,187.7zM789.3,885.3L234.7,885.3c-6.4,0 -10.7,-4.3 -10.7,-10.7L224,149.3c0,-6.4 4.3,-10.7 10.7,-10.7h311.5c-2.1,4.3 -2.1,6.4 -2.1,10.7v170.7c0,40.5 34.1,74.7 74.7,74.7h170.7c4.3,0 6.4,0 10.7,-2.1L800,874.7c0,6.4 -4.3,10.7 -10.7,10.7z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M640,586.7H384c-17.1,0 -32,14.9 -32,32s14.9,32 32,32h256c17.1,0 32,-14.9 32,-32s-14.9,-32 -32,-32z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
</vector>
|
||||||
@ -1,9 +1,9 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="366.8dp"
|
android:width="24dp"
|
||||||
android:height="256dp"
|
android:height="17dp"
|
||||||
android:viewportWidth="1467"
|
android:viewportWidth="1467"
|
||||||
android:viewportHeight="1024">
|
android:viewportHeight="1024">
|
||||||
<path
|
<path
|
||||||
android:pathData="M299.1,18.5l917.2,917.2a34.1,34.1 0,0 1,-48.3 48.3L250.9,66.7A34.1,34.1 0,1 1,299.1 18.5zM324.6,188.7l50.6,50.6a918.1,918.1 0,0 0,-113.9 67.5,829.3 829.3,0 0,0 -93.1,75.2l-14.1,13.6c-4.5,4.5 -8.9,8.9 -13.1,13.3l-12,12.9A438.3,438.3 0,0 0,99.7 457.4l-7.3,10.6c-10,15.2 -15.5,27.6 -15.9,35.9 -0.6,15.4 23.2,51.4 64.1,93.3l12.7,12.8c28.7,27.9 64.2,57.8 104.4,85.5 140.2,96.5 308.7,155.6 475.9,155.6 75.1,0 150,-11 222.1,-31.2l54.7,54.7c-85.3,27.7 -178.8,44.7 -276.8,44.7 -256.6,0 -483.8,-126.3 -612.9,-246l-13.2,-12.6c-12.9,-12.6 -24.6,-25 -35.2,-37.1l-10.1,-12a468.4,468.4 0,0 1,-4.8 -5.9l-8.9,-11.7C21.6,557.3 7.3,524.7 8.3,501.2c0.9,-21.5 13.8,-50.7 37,-83.5l8.6,-11.7 9.5,-12 5.1,-6.1 10.7,-12.4 5.6,-6.2 11.9,-12.6 12.6,-12.8c4.4,-4.3 8.8,-8.6 13.4,-12.9l14.1,-12.9c12.1,-10.8 24.9,-21.6 38.4,-32.3l16.6,-12.8a976.1,976.1 0,0 1,132.7 -84.2zM733.6,83c400.6,0 725.3,284.8 725.3,418.1 0,42.4 -32.9,100.2 -90.6,159.2l-12.8,12.7 -6.7,6.3 -13.9,12.7c-4.7,4.2 -9.6,8.4 -14.6,12.6l-15.3,12.6c-5.2,4.2 -10.5,8.3 -16,12.5l-16.6,12.4a929.4,929.4 0,0 1,-125.5 76.1l-51,-50.9a880.5,880.5 0,0 0,112.4 -63.8c58.2,-39 106.9,-82.3 140.3,-123.6 28.1,-34.7 41.9,-64.1 41.9,-78.7 0,-14.6 -13.8,-44 -41.8,-78.7 -33.4,-41.3 -82.1,-84.7 -140.3,-123.6 -136.9,-91.6 -305.5,-147.6 -474.9,-147.6 -74.3,0 -148.5,11.7 -220.2,33.2l-54.1,-54.2c84.4,-29.1 177,-47.2 274.4,-47.2zM536.7,400.8l52,52a152.7,152.7 0,0 0,193.2 193.2l52,52.1a220.9,220.9 0,0 1,-297.2 -297.3zM733.6,280.2a220.9,220.9 0,0 1,196.9 321.3L878.5,549.5a152.7,152.7 0,0 0,-193.2 -193.2L633.2,304.3a220,220 0,0 1,100.4 -24.1z"
|
android:pathData="M299.1,18.5l917.2,917.2a34.1,34.1 0,0 1,-48.3 48.3L250.9,66.7A34.1,34.1 0,1 1,299.1 18.5zM324.6,188.7l50.6,50.6a918.1,918.1 0,0 0,-113.9 67.5,829.3 829.3,0 0,0 -93.1,75.2l-14.1,13.6c-4.5,4.5 -8.9,8.9 -13.1,13.3l-12,12.9A438.3,438.3 0,0 0,99.7 457.4l-7.3,10.6c-10,15.2 -15.5,27.6 -15.9,35.9 -0.6,15.4 23.2,51.4 64.1,93.3l12.7,12.8c28.7,27.9 64.2,57.8 104.4,85.5 140.2,96.5 308.7,155.6 475.9,155.6 75.1,0 150,-11 222.1,-31.2l54.7,54.7c-85.3,27.7 -178.8,44.7 -276.8,44.7 -256.6,0 -483.8,-126.3 -612.9,-246l-13.2,-12.6c-12.9,-12.6 -24.6,-25 -35.2,-37.1l-10.1,-12a468.4,468.4 0,0 1,-4.8 -5.9l-8.9,-11.7C21.6,557.3 7.3,524.7 8.3,501.2c0.9,-21.5 13.8,-50.7 37,-83.5l8.6,-11.7 9.5,-12 5.1,-6.1 10.7,-12.4 5.6,-6.2 11.9,-12.6 12.6,-12.8c4.4,-4.3 8.8,-8.6 13.4,-12.9l14.1,-12.9c12.1,-10.8 24.9,-21.6 38.4,-32.3l16.6,-12.8a976.1,976.1 0,0 1,132.7 -84.2zM733.6,83c400.6,0 725.3,284.8 725.3,418.1 0,42.4 -32.9,100.2 -90.6,159.2l-12.8,12.7 -6.7,6.3 -13.9,12.7c-4.7,4.2 -9.6,8.4 -14.6,12.6l-15.3,12.6c-5.2,4.2 -10.5,8.3 -16,12.5l-16.6,12.4a929.4,929.4 0,0 1,-125.5 76.1l-51,-50.9a880.5,880.5 0,0 0,112.4 -63.8c58.2,-39 106.9,-82.3 140.3,-123.6 28.1,-34.7 41.9,-64.1 41.9,-78.7 0,-14.6 -13.8,-44 -41.8,-78.7 -33.4,-41.3 -82.1,-84.7 -140.3,-123.6 -136.9,-91.6 -305.5,-147.6 -474.9,-147.6 -74.3,0 -148.5,11.7 -220.2,33.2l-54.1,-54.2c84.4,-29.1 177,-47.2 274.4,-47.2zM536.7,400.8l52,52a152.7,152.7 0,0 0,193.2 193.2l52,52.1a220.9,220.9 0,0 1,-297.2 -297.3zM733.6,280.2a220.9,220.9 0,0 1,196.9 321.3L878.5,549.5a152.7,152.7 0,0 0,-193.2 -193.2L633.2,304.3a220,220 0,0 1,100.4 -24.1z"
|
||||||
android:fillColor="#bfbfbf"/>
|
android:fillColor="#666666"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
9
app/src/main/res/drawable/print.xml
Normal file
9
app/src/main/res/drawable/print.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="256dp"
|
||||||
|
android:height="256dp"
|
||||||
|
android:viewportWidth="1024"
|
||||||
|
android:viewportHeight="1024">
|
||||||
|
<path
|
||||||
|
android:pathData="M819.2,364.8h-44.8L774.4,128c0,-17.1 -14.9,-32 -32,-32L281.6,96c-17.1,0 -32,14.9 -32,32v236.8L204.8,364.8c-59.7,0 -108.8,49.1 -108.8,108.8v192c0,59.7 49.1,108.8 108.8,108.8h44.8L249.6,896c0,17.1 14.9,32 32,32h460.8c17.1,0 32,-14.9 32,-32v-121.6h44.8c59.7,0 108.8,-49.1 108.8,-108.8v-192c0,-59.7 -49.1,-108.8 -108.8,-108.8zM313.6,160h396.8v204.8L313.6,364.8L313.6,160zM710.4,864L313.6,864L313.6,620.8h396.8v243.2zM864,665.6c0,25.6 -19.2,44.8 -44.8,44.8h-44.8v-121.6c0,-17.1 -14.9,-32 -32,-32L281.6,556.8c-17.1,0 -32,14.9 -32,32v121.6L204.8,710.4c-25.6,0 -44.8,-19.2 -44.8,-44.8v-192c0,-25.6 19.2,-44.8 44.8,-44.8h614.4c25.6,0 44.8,19.2 44.8,44.8v192z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
</vector>
|
||||||
15
app/src/main/res/drawable/prompt.xml
Normal file
15
app/src/main/res/drawable/prompt.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="256dp"
|
||||||
|
android:height="256dp"
|
||||||
|
android:viewportWidth="1024"
|
||||||
|
android:viewportHeight="1024">
|
||||||
|
<path
|
||||||
|
android:pathData="M512,74.7C270.9,74.7 74.7,270.9 74.7,512S270.9,949.3 512,949.3 949.3,753.1 949.3,512 753.1,74.7 512,74.7zM512,885.3c-204.8,0 -373.3,-168.5 -373.3,-373.3S307.2,138.7 512,138.7 885.3,307.2 885.3,512 716.8,885.3 512,885.3z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M512,320m-42.7,0a42.7,42.7 0,1 0,85.3 0,42.7 42.7,0 1,0 -85.3,0Z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M512,437.3c-17.1,0 -32,14.9 -32,32v234.7c0,17.1 14.9,32 32,32s32,-14.9 32,-32V469.3c0,-17.1 -14.9,-32 -32,-32z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
</vector>
|
||||||
9
app/src/main/res/drawable/rename_text.xml
Normal file
9
app/src/main/res/drawable/rename_text.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="256dp"
|
||||||
|
android:height="256dp"
|
||||||
|
android:viewportWidth="1024"
|
||||||
|
android:viewportHeight="1024">
|
||||||
|
<path
|
||||||
|
android:pathData="M853.3,138.7H170.7c-17.1,0 -32,14.9 -32,32v128c0,17.1 14.9,32 32,32s32,-14.9 32,-32V202.7h277.3v618.7H384c-17.1,0 -32,14.9 -32,32s14.9,32 32,32h256c17.1,0 32,-14.9 32,-32s-14.9,-32 -32,-32h-96v-618.7h277.3V298.7c0,17.1 14.9,32 32,32s32,-14.9 32,-32V170.7c0,-17.1 -14.9,-32 -32,-32z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
</vector>
|
||||||
12
app/src/main/res/drawable/share.xml
Normal file
12
app/src/main/res/drawable/share.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="256dp"
|
||||||
|
android:height="256dp"
|
||||||
|
android:viewportWidth="1024"
|
||||||
|
android:viewportHeight="1024">
|
||||||
|
<path
|
||||||
|
android:pathData="M874.7,544c-17.1,0 -32,14.9 -32,32v256c0,6.4 -4.3,10.7 -10.7,10.7H192c-6.4,0 -10.7,-4.3 -10.7,-10.7V192c0,-6.4 4.3,-10.7 10.7,-10.7h256c17.1,0 32,-14.9 32,-32s-14.9,-32 -32,-32H192C151.5,117.3 117.3,151.5 117.3,192v640c0,40.5 34.1,74.7 74.7,74.7h640c40.5,0 74.7,-34.1 74.7,-74.7V576c0,-17.1 -14.9,-32 -32,-32z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M874.7,117.3H640c-17.1,0 -32,14.9 -32,32s14.9,32 32,32h157.9L509.9,467.2c-12.8,12.8 -12.8,32 0,44.8 6.4,6.4 14.9,8.5 23.5,8.5s17.1,-2.1 23.5,-8.5l285.9,-285.9V384c0,17.1 14.9,32 32,32s32,-14.9 32,-32V149.3c0,-17.1 -14.9,-32 -32,-32z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
</vector>
|
||||||
@ -1,9 +1,9 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="433dp"
|
android:width="24dp"
|
||||||
android:height="256dp"
|
android:height="14dp"
|
||||||
android:viewportWidth="1732"
|
android:viewportWidth="1732"
|
||||||
android:viewportHeight="1024">
|
android:viewportHeight="1024">
|
||||||
<path
|
<path
|
||||||
android:pathData="M872.8,34.5c462.2,0 836.9,328.7 836.9,482.5 0,49 -37.9,115.6 -104.5,183.7l-14.7,14.6 -7.7,7.3 -16,14.6c-5.5,4.9 -11.1,9.7 -16.8,14.6l-17.6,14.5c-6,4.8 -12.2,9.6 -18.4,14.4l-19.2,14.3c-153.2,110.8 -375.1,204.5 -622,204.5 -296,0 -558.2,-145.7 -707.2,-283.9l-15.3,-14.5c-14.8,-14.5 -28.4,-28.8 -40.6,-42.8l-11.7,-13.9a540.4,540.4 0,0 1,-5.5 -6.9l-10.3,-13.5C51.2,581.7 34.8,544.1 35.8,516.9c1,-24.9 16,-58.4 42.7,-96.4l10,-13.5 10.9,-13.9c1.9,-2.4 3.8,-4.7 5.8,-7.1l12.3,-14.3 6.5,-7.2 13.7,-14.6 14.6,-14.7c5,-4.9 10.2,-9.9 15.5,-14.8l16.3,-14.9c13.9,-12.4 28.8,-24.9 44.3,-37.3l19.1,-14.8c152.8,-115.4 375.5,-219.1 625.2,-219.1zM872.8,113.2c-192.4,0 -384.2,67.9 -544.9,179.4a957,957 0,0 0,-107.4 86.7l-16.3,15.6c-5.2,5.2 -10.3,10.3 -15.1,15.4l-13.9,14.9a505.7,505.7 0,0 0,-33.8 41.2l-8.4,12.2c-11.5,17.6 -18,31.9 -18.4,41.5 -0.7,17.7 26.9,59.2 74,107.6l14.7,14.7c33.1,32.2 74,66.6 120.5,98.6 161.8,111.3 356.2,179.6 549.1,179.6 195.5,0 390.1,-64.5 548,-170.2 67.2,-45 123.4,-95 161.9,-142.7 32.3,-40 48.3,-74 48.3,-90.8 0,-16.8 -16,-50.7 -48.2,-90.8 -38.5,-47.7 -94.7,-97.7 -161.9,-142.7 -157.9,-105.7 -352.5,-170.3 -548,-170.3zM872.8,262a254.9,254.9 0,1 1,0 509.9,254.9 254.9,0 0,1 0,-509.9zM872.8,340.8a176.2,176.2 0,1 0,0 352.4,176.2 176.2,0 0,0 0,-352.4z"
|
android:pathData="M872.8,34.5c462.2,0 836.9,328.7 836.9,482.5 0,49 -37.9,115.6 -104.5,183.7l-14.7,14.6 -7.7,7.3 -16,14.6c-5.5,4.9 -11.1,9.7 -16.8,14.6l-17.6,14.5c-6,4.8 -12.2,9.6 -18.4,14.4l-19.2,14.3c-153.2,110.8 -375.1,204.5 -622,204.5 -296,0 -558.2,-145.7 -707.2,-283.9l-15.3,-14.5c-14.8,-14.5 -28.4,-28.8 -40.6,-42.8l-11.7,-13.9a540.4,540.4 0,0 1,-5.5 -6.9l-10.3,-13.5C51.2,581.7 34.8,544.1 35.8,516.9c1,-24.9 16,-58.4 42.7,-96.4l10,-13.5 10.9,-13.9c1.9,-2.4 3.8,-4.7 5.8,-7.1l12.3,-14.3 6.5,-7.2 13.7,-14.6 14.6,-14.7c5,-4.9 10.2,-9.9 15.5,-14.8l16.3,-14.9c13.9,-12.4 28.8,-24.9 44.3,-37.3l19.1,-14.8c152.8,-115.4 375.5,-219.1 625.2,-219.1zM872.8,113.2c-192.4,0 -384.2,67.9 -544.9,179.4a957,957 0,0 0,-107.4 86.7l-16.3,15.6c-5.2,5.2 -10.3,10.3 -15.1,15.4l-13.9,14.9a505.7,505.7 0,0 0,-33.8 41.2l-8.4,12.2c-11.5,17.6 -18,31.9 -18.4,41.5 -0.7,17.7 26.9,59.2 74,107.6l14.7,14.7c33.1,32.2 74,66.6 120.5,98.6 161.8,111.3 356.2,179.6 549.1,179.6 195.5,0 390.1,-64.5 548,-170.2 67.2,-45 123.4,-95 161.9,-142.7 32.3,-40 48.3,-74 48.3,-90.8 0,-16.8 -16,-50.7 -48.2,-90.8 -38.5,-47.7 -94.7,-97.7 -161.9,-142.7 -157.9,-105.7 -352.5,-170.3 -548,-170.3zM872.8,262a254.9,254.9 0,1 1,0 509.9,254.9 254.9,0 0,1 0,-509.9zM872.8,340.8a176.2,176.2 0,1 0,0 352.4,176.2 176.2,0 0,0 0,-352.4z"
|
||||||
android:fillColor="#bfbfbf"/>
|
android:fillColor="#666666"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
293
app/src/main/res/layout/dialog_list_more.xml
Normal file
293
app/src/main/res/layout/dialog_list_more.xml
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:background="@drawable/dr_dialog_indicator_bg" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:background="@drawable/dr_item_img_frame">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/tvFileImg"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:src="@mipmap/ic_launcher_round" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/lock_layout"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:background="@drawable/dr_item_lock_bg"
|
||||||
|
android:gravity="center"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/lock" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvFileName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="middle"
|
||||||
|
android:fontFamily="@font/poppins_medium"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/grey_text_color"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvFileDate"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/black_60"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvFileSize"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/black_60"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/collectBtn"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/collectIv"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/collect" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/renameFileBtn"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/rename_text" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:text="@string/rename_file"
|
||||||
|
android:textColor="@color/grey_text_color"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/prompt" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:text="@string/file_details"
|
||||||
|
android:textColor="@color/grey_text_color"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/share" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:text="@string/share_file"
|
||||||
|
android:textColor="@color/grey_text_color"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/print" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:text="@string/print_pdf"
|
||||||
|
android:textColor="@color/grey_text_color"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:background="@color/line_color" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/duplicate" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:fontFamily="@font/poppins_medium"
|
||||||
|
android:text="@string/duplicate_file"
|
||||||
|
android:textColor="@color/grey_text_color"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/lock" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:fontFamily="@font/poppins_medium"
|
||||||
|
android:text="@string/set_password"
|
||||||
|
android:textColor="@color/grey_text_color"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/file_delete" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:fontFamily="@font/poppins_medium"
|
||||||
|
android:text="@string/delete_file"
|
||||||
|
android:textColor="@color/grey_text_color"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
@ -38,7 +38,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/enter_password"
|
android:hint="@string/enter_password"
|
||||||
app:endIconMode="password_toggle"
|
app:endIconMode="password_toggle"
|
||||||
app:passwordToggleEnabled="true">
|
app:endIconDrawable="@drawable/dr_password_state">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/etPassword"
|
android:id="@+id/etPassword"
|
||||||
@ -50,21 +50,6 @@
|
|||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/showPasswordBtn"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_alignEnd="@id/tilPassword"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/showPasswordIv"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:src="@drawable/hide_password" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/enter_password"
|
android:hint="@string/enter_password"
|
||||||
|
app:endIconDrawable="@drawable/dr_password_state"
|
||||||
app:endIconMode="password_toggle"
|
app:endIconMode="password_toggle"
|
||||||
app:passwordToggleEnabled="true">
|
app:passwordToggleEnabled="true">
|
||||||
|
|
||||||
@ -50,22 +51,6 @@
|
|||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/enterShowPasswordBtn"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_alignEnd="@id/tilPassword"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/enterShowPasswordIv"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:src="@drawable/hide_password" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
@ -78,6 +63,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/confirm_password"
|
android:hint="@string/confirm_password"
|
||||||
|
app:endIconDrawable="@drawable/dr_password_state"
|
||||||
app:endIconMode="password_toggle"
|
app:endIconMode="password_toggle"
|
||||||
app:passwordToggleEnabled="true">
|
app:passwordToggleEnabled="true">
|
||||||
|
|
||||||
@ -91,22 +77,6 @@
|
|||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/confirmShowPasswordBtn"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_alignEnd="@id/tilConfirmPassword"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/confirmShowPasswordIv"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:src="@drawable/hide_password" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|||||||
72
app/src/main/res/layout/dialog_rename_file.xml
Normal file
72
app/src/main/res/layout/dialog_rename_file.xml
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/dr_rounded_corner_12_bg_white"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="24dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTitle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:fontFamily="@font/poppins_semibold"
|
||||||
|
android:text="@string/rename_file"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/tilName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/enter_name"
|
||||||
|
app:endIconDrawable="@drawable/delete"
|
||||||
|
app:endIconMode="clear_text">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="end"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvCancel"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="@font/poppins_regular"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/cancel"
|
||||||
|
android:textColor="@color/black_80" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvConfirm"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/poppins_medium"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:text="@string/ok"
|
||||||
|
android:textColor="@color/black" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@ -1,9 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/dr_rounded_corner_12_bg_white"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|||||||
@ -13,4 +13,5 @@
|
|||||||
<color name="bg_color">#F6F6F6</color>
|
<color name="bg_color">#F6F6F6</color>
|
||||||
<color name="line_color">#E0E0E0</color>
|
<color name="line_color">#E0E0E0</color>
|
||||||
<color name="black_img_color">#2c2c2c</color>
|
<color name="black_img_color">#2c2c2c</color>
|
||||||
|
<color name="grey_text_color">#666666</color>
|
||||||
</resources>
|
</resources>
|
||||||
@ -39,4 +39,21 @@
|
|||||||
<string name="pdf_loading_failed">PDF loading failed</string>
|
<string name="pdf_loading_failed">PDF loading failed</string>
|
||||||
<string name="password_too_short">Password must be at least 4 characters</string>
|
<string name="password_too_short">Password must be at least 4 characters</string>
|
||||||
<string name="password_not_match">Passwords do not match</string>
|
<string name="password_not_match">Passwords do not match</string>
|
||||||
|
<string name="rename_file">Rename</string>
|
||||||
|
<string name="file_details">Details</string>
|
||||||
|
<string name="share_file">Share</string>
|
||||||
|
<string name="print_pdf">Print</string>
|
||||||
|
<string name="added_to_favorites">Added to Favorite</string>
|
||||||
|
<string name="removed_from_favorites">Removed from Favorites</string>
|
||||||
|
<string name="delete_file">Delete File</string>
|
||||||
|
<string name="set_password">Set Password</string>
|
||||||
|
<string name="remove_password">Remove Password</string>
|
||||||
|
<string name="duplicate_file">Duplicate File</string>
|
||||||
|
<string name="enter_name">Enter a name</string>
|
||||||
|
<string name="name_not_empty">File name cannot be empty</string>
|
||||||
|
<string name="name_not_changed">File name has not been changed</string>
|
||||||
|
<string name="name_invalid_chars">File name contains invalid characters: / \ : * ? " < > |</string>
|
||||||
|
<string name="name_too_long">File name is too long (max 255 characters)</string>
|
||||||
|
<string name="name_already_exists">A file with the same name already exists</string>
|
||||||
|
<string name="name_start_end_space">File name cannot start or end with space</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in New Issue
Block a user