mirror of
https://github.com/FossifyOrg/File-Manager.git
synced 2026-11-04 12:03:02 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2482ee5dc | ||
|
|
de5b6da9d5 | ||
|
|
4812bc8d4b | ||
|
|
3ec4591b58 | ||
|
|
d11a710106 | ||
|
|
2cf0fdf7d1 | ||
|
|
25fe232c27 | ||
|
|
f733553ff3 | ||
|
|
5b278f6e4a | ||
|
|
fec28af74f | ||
|
|
eb4d38d25a | ||
|
|
8647071c66 | ||
|
|
630d7b2cea | ||
|
|
223e644f36 | ||
|
|
055bfbd3b8 | ||
|
|
ceb7a5f2a2 | ||
|
|
20aee9162d | ||
|
|
7a5f797a2a | ||
|
|
10a83a18b1 | ||
|
|
fb3384fb08 | ||
|
|
666c8d8c53 |
No files matched your search
@@ -1,2 +1,2 @@
|
|||||||
# Auto-generated file. DO NOT EDIT.
|
# Auto-generated file. DO NOT EDIT.
|
||||||
1.2.2
|
1.3.0
|
||||||
@@ -18,7 +18,7 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- label: "I made sure that there are **no existing issues** - [open](https://github.com/FossifyOrg/File-Manager/issues) or [closed](https://github.com/FossifyOrg/File-Manager/issues?q=is%3Aissue+is%3Aclosed) - to which I could contribute my information."
|
- label: "I made sure that there are **no existing issues** - [open](https://github.com/FossifyOrg/File-Manager/issues) or [closed](https://github.com/FossifyOrg/File-Manager/issues?q=is%3Aissue+is%3Aclosed) - to which I could contribute my information."
|
||||||
required: true
|
required: true
|
||||||
- label: "I made sure that there are **no existing discussions** - [open](https://github.com/FossifyOrg/File-Manager/discussions) or [closed](https://github.com/FossifyOrg/File-Manager/discussions?discussions_q=is%3Aclosed) - to which I could contribute my information."
|
- label: "I made sure that there are **no existing discussions** - [open](https://github.com/orgs/FossifyOrg/discussions?discussions_q=is:open+label:filemanager) or [closed](https://github.com/orgs/FossifyOrg/discussions?discussions_q=is:closed+label:filemanager) - to which I could contribute my information."
|
||||||
required: true
|
required: true
|
||||||
- label: "I have read the FAQs inside the app (Menu -> About -> FAQs) and my problem isn't listed."
|
- label: "I have read the FAQs inside the app (Menu -> About -> FAQs) and my problem isn't listed."
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ body:
|
|||||||
options:
|
options:
|
||||||
- label: "I made sure that there are **no existing issues** - [open](https://github.com/FossifyOrg/File-Manager/issues) or [closed](https://github.com/FossifyOrg/File-Manager/issues?q=is%3Aissue+is%3Aclosed) - to which I could contribute my information."
|
- label: "I made sure that there are **no existing issues** - [open](https://github.com/FossifyOrg/File-Manager/issues) or [closed](https://github.com/FossifyOrg/File-Manager/issues?q=is%3Aissue+is%3Aclosed) - to which I could contribute my information."
|
||||||
required: true
|
required: true
|
||||||
- label: "I made sure that there are **no existing discussions** - [open](https://github.com/FossifyOrg/File-Manager/discussions) or [closed](https://github.com/FossifyOrg/File-Manager/discussions?discussions_q=is%3Aclosed) - to which I could contribute my information."
|
- label: "I made sure that there are **no existing discussions** - [open](https://github.com/orgs/FossifyOrg/discussions?discussions_q=is:open+label:filemanager) or [closed](https://github.com/orgs/FossifyOrg/discussions?discussions_q=is:closed+label:filemanager) - to which I could contribute my information."
|
||||||
required: true
|
required: true
|
||||||
- label: "I have read the FAQs inside the app (Menu -> About -> FAQs) and my problem isn't listed."
|
- label: "I have read the FAQs inside the app (Menu -> About -> FAQs) and my problem isn't listed."
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
+31
-1
@@ -6,6 +6,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [1.3.0] - 2025-09-30
|
||||||
|
### Added
|
||||||
|
- Added a separate "Save as" option in the text editor ([#224])
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Save button now overwrites files directly in the text editor ([#224])
|
||||||
|
- Search now ignores accents and diacritics ([#95])
|
||||||
|
- Updated translations
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed folders showing up incorrectly as files in copy/move dialog ([#267])
|
||||||
|
- Fixed error when saving files with unsupported characters ([#250])
|
||||||
|
- Fixed missing permission prompt on initial "Save as" launch ([#85])
|
||||||
|
- Fixed printing text files containing a "#" ([#104])
|
||||||
|
- Fixed files in hidden folders showing up in recent tab ([#217])
|
||||||
|
|
||||||
|
## [1.2.3] - 2025-09-15
|
||||||
|
### Fixed
|
||||||
|
- Fixed folders showing up incorrectly as files in some cases ([#80])
|
||||||
|
|
||||||
## [1.2.2] - 2025-09-01
|
## [1.2.2] - 2025-09-01
|
||||||
### Changed
|
### Changed
|
||||||
- Updated translations
|
- Updated translations
|
||||||
@@ -58,6 +78,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
[#27]: https://github.com/FossifyOrg/File-Manager/issues/27
|
[#27]: https://github.com/FossifyOrg/File-Manager/issues/27
|
||||||
[#37]: https://github.com/FossifyOrg/File-Manager/issues/37
|
[#37]: https://github.com/FossifyOrg/File-Manager/issues/37
|
||||||
|
[#80]: https://github.com/FossifyOrg/File-Manager/issues/80
|
||||||
|
[#85]: https://github.com/FossifyOrg/File-Manager/issues/85
|
||||||
|
[#95]: https://github.com/FossifyOrg/File-Manager/issues/95
|
||||||
|
[#104]: https://github.com/FossifyOrg/File-Manager/issues/104
|
||||||
[#105]: https://github.com/FossifyOrg/File-Manager/issues/105
|
[#105]: https://github.com/FossifyOrg/File-Manager/issues/105
|
||||||
[#106]: https://github.com/FossifyOrg/File-Manager/issues/106
|
[#106]: https://github.com/FossifyOrg/File-Manager/issues/106
|
||||||
[#120]: https://github.com/FossifyOrg/File-Manager/issues/120
|
[#120]: https://github.com/FossifyOrg/File-Manager/issues/120
|
||||||
@@ -65,9 +89,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
[#149]: https://github.com/FossifyOrg/File-Manager/issues/149
|
[#149]: https://github.com/FossifyOrg/File-Manager/issues/149
|
||||||
[#150]: https://github.com/FossifyOrg/File-Manager/issues/150
|
[#150]: https://github.com/FossifyOrg/File-Manager/issues/150
|
||||||
[#176]: https://github.com/FossifyOrg/File-Manager/issues/176
|
[#176]: https://github.com/FossifyOrg/File-Manager/issues/176
|
||||||
|
[#217]: https://github.com/FossifyOrg/File-Manager/issues/217
|
||||||
|
[#224]: https://github.com/FossifyOrg/File-Manager/issues/224
|
||||||
|
[#250]: https://github.com/FossifyOrg/File-Manager/issues/250
|
||||||
[#251]: https://github.com/FossifyOrg/File-Manager/issues/251
|
[#251]: https://github.com/FossifyOrg/File-Manager/issues/251
|
||||||
|
[#267]: https://github.com/FossifyOrg/File-Manager/issues/267
|
||||||
|
|
||||||
[Unreleased]: https://github.com/FossifyOrg/File-Manager/compare/1.2.2...HEAD
|
[Unreleased]: https://github.com/FossifyOrg/File-Manager/compare/1.3.0...HEAD
|
||||||
|
[1.3.0]: https://github.com/FossifyOrg/File-Manager/compare/1.2.3...1.3.0
|
||||||
|
[1.2.3]: https://github.com/FossifyOrg/File-Manager/compare/1.2.2...1.2.3
|
||||||
[1.2.2]: https://github.com/FossifyOrg/File-Manager/compare/1.2.0...1.2.2
|
[1.2.2]: https://github.com/FossifyOrg/File-Manager/compare/1.2.0...1.2.2
|
||||||
[1.2.0]: https://github.com/FossifyOrg/File-Manager/compare/1.1.0...1.2.0
|
[1.2.0]: https://github.com/FossifyOrg/File-Manager/compare/1.1.0...1.2.0
|
||||||
[1.1.0]: https://github.com/FossifyOrg/File-Manager/compare/1.0.1...1.1.0
|
[1.1.0]: https://github.com/FossifyOrg/File-Manager/compare/1.0.1...1.1.0
|
||||||
|
|||||||
+1
-1
@@ -182,7 +182,7 @@ GEM
|
|||||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||||
uber (< 0.2.0)
|
uber (< 0.2.0)
|
||||||
retriable (3.1.2)
|
retriable (3.1.2)
|
||||||
rexml (3.4.1)
|
rexml (3.4.2)
|
||||||
rouge (3.28.0)
|
rouge (3.28.0)
|
||||||
ruby2_keywords (0.0.5)
|
ruby2_keywords (0.0.5)
|
||||||
rubyzip (2.4.1)
|
rubyzip (2.4.1)
|
||||||
|
|||||||
@@ -1,22 +1,17 @@
|
|||||||
package org.fossify.filemanager.activities
|
package org.fossify.filemanager.activities
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.media.RingtoneManager
|
import android.media.RingtoneManager
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.provider.Settings
|
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import com.stericson.RootTools.RootTools
|
import com.stericson.RootTools.RootTools
|
||||||
import me.grantland.widget.AutofitHelper
|
import me.grantland.widget.AutofitHelper
|
||||||
import org.fossify.commons.dialogs.ConfirmationAdvancedDialog
|
|
||||||
import org.fossify.commons.dialogs.RadioGroupDialog
|
import org.fossify.commons.dialogs.RadioGroupDialog
|
||||||
import org.fossify.commons.extensions.appLaunched
|
import org.fossify.commons.extensions.appLaunched
|
||||||
import org.fossify.commons.extensions.appLockManager
|
import org.fossify.commons.extensions.appLockManager
|
||||||
@@ -43,7 +38,6 @@ import org.fossify.commons.extensions.launchMoreAppsFromUsIntent
|
|||||||
import org.fossify.commons.extensions.onGlobalLayout
|
import org.fossify.commons.extensions.onGlobalLayout
|
||||||
import org.fossify.commons.extensions.onTabSelectionChanged
|
import org.fossify.commons.extensions.onTabSelectionChanged
|
||||||
import org.fossify.commons.extensions.sdCardPath
|
import org.fossify.commons.extensions.sdCardPath
|
||||||
import org.fossify.commons.extensions.showErrorToast
|
|
||||||
import org.fossify.commons.extensions.toast
|
import org.fossify.commons.extensions.toast
|
||||||
import org.fossify.commons.extensions.updateBottomTabItemColors
|
import org.fossify.commons.extensions.updateBottomTabItemColors
|
||||||
import org.fossify.commons.extensions.viewBinding
|
import org.fossify.commons.extensions.viewBinding
|
||||||
@@ -59,7 +53,6 @@ import org.fossify.commons.helpers.TAB_RECENT_FILES
|
|||||||
import org.fossify.commons.helpers.TAB_STORAGE_ANALYSIS
|
import org.fossify.commons.helpers.TAB_STORAGE_ANALYSIS
|
||||||
import org.fossify.commons.helpers.VIEW_TYPE_GRID
|
import org.fossify.commons.helpers.VIEW_TYPE_GRID
|
||||||
import org.fossify.commons.helpers.ensureBackgroundThread
|
import org.fossify.commons.helpers.ensureBackgroundThread
|
||||||
import org.fossify.commons.helpers.isRPlus
|
|
||||||
import org.fossify.commons.models.FAQItem
|
import org.fossify.commons.models.FAQItem
|
||||||
import org.fossify.commons.models.RadioItem
|
import org.fossify.commons.models.RadioItem
|
||||||
import org.fossify.commons.models.Release
|
import org.fossify.commons.models.Release
|
||||||
@@ -84,7 +77,6 @@ import java.io.File
|
|||||||
class MainActivity : SimpleActivity() {
|
class MainActivity : SimpleActivity() {
|
||||||
companion object {
|
companion object {
|
||||||
private const val BACK_PRESS_TIMEOUT = 5000
|
private const val BACK_PRESS_TIMEOUT = 5000
|
||||||
private const val MANAGE_STORAGE_RC = 201
|
|
||||||
private const val PICKED_PATH = "picked_path"
|
private const val PICKED_PATH = "picked_path"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,15 +273,6 @@ class MainActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
|
||||||
super.onActivityResult(requestCode, resultCode, resultData)
|
|
||||||
isAskingPermissions = false
|
|
||||||
if (requestCode == MANAGE_STORAGE_RC && isRPlus()) {
|
|
||||||
actionOnPermission?.invoke(Environment.isExternalStorageManager())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateMenuColors() {
|
private fun updateMenuColors() {
|
||||||
updateStatusbarColor(getProperBackgroundColor())
|
updateStatusbarColor(getProperBackgroundColor())
|
||||||
binding.mainMenu.updateColors()
|
binding.mainMenu.updateColors()
|
||||||
@@ -323,38 +306,6 @@ class MainActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
|
||||||
private fun handleStoragePermission(callback: (granted: Boolean) -> Unit) {
|
|
||||||
actionOnPermission = null
|
|
||||||
if (hasStoragePermission()) {
|
|
||||||
callback(true)
|
|
||||||
} else {
|
|
||||||
if (isRPlus()) {
|
|
||||||
ConfirmationAdvancedDialog(this, "", R.string.access_storage_prompt, R.string.ok, 0, false) { success ->
|
|
||||||
if (success) {
|
|
||||||
isAskingPermissions = true
|
|
||||||
actionOnPermission = callback
|
|
||||||
try {
|
|
||||||
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
|
|
||||||
intent.addCategory("android.intent.category.DEFAULT")
|
|
||||||
intent.data = Uri.parse("package:$packageName")
|
|
||||||
startActivityForResult(intent, MANAGE_STORAGE_RC)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
showErrorToast(e)
|
|
||||||
val intent = Intent()
|
|
||||||
intent.action = Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
|
|
||||||
startActivityForResult(intent, MANAGE_STORAGE_RC)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
handlePermission(PERMISSION_WRITE_STORAGE, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initFileManager(refreshRecents: Boolean) {
|
private fun initFileManager(refreshRecents: Boolean) {
|
||||||
if (intent.action == Intent.ACTION_VIEW && intent.data != null) {
|
if (intent.action == Intent.ACTION_VIEW && intent.data != null) {
|
||||||
val data = intent.data
|
val data = intent.data
|
||||||
|
|||||||
@@ -133,10 +133,11 @@ class MimeTypesActivity : SimpleActivity(), ItemOperationsListener {
|
|||||||
override fun selectedPaths(paths: ArrayList<String>) {}
|
override fun selectedPaths(paths: ArrayList<String>) {}
|
||||||
|
|
||||||
fun searchQueryChanged(text: String) {
|
fun searchQueryChanged(text: String) {
|
||||||
val searchText = text.trim()
|
val normalizedText = text.normalizeString()
|
||||||
lastSearchedText = searchText
|
val searchNormalizedText = normalizedText.trim()
|
||||||
|
lastSearchedText = searchNormalizedText
|
||||||
when {
|
when {
|
||||||
searchText.isEmpty() -> {
|
searchNormalizedText.isEmpty() -> {
|
||||||
binding.apply {
|
binding.apply {
|
||||||
mimetypesFastscroller.beVisible()
|
mimetypesFastscroller.beVisible()
|
||||||
getRecyclerAdapter()?.updateItems(storedItems)
|
getRecyclerAdapter()?.updateItems(storedItems)
|
||||||
@@ -145,7 +146,7 @@ class MimeTypesActivity : SimpleActivity(), ItemOperationsListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
searchText.length == 1 -> {
|
searchNormalizedText.length == 1 -> {
|
||||||
binding.apply {
|
binding.apply {
|
||||||
mimetypesFastscroller.beGone()
|
mimetypesFastscroller.beGone()
|
||||||
mimetypesPlaceholder.beVisible()
|
mimetypesPlaceholder.beVisible()
|
||||||
@@ -155,11 +156,13 @@ class MimeTypesActivity : SimpleActivity(), ItemOperationsListener {
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
if (lastSearchedText != searchText) {
|
if (lastSearchedText != searchNormalizedText) {
|
||||||
return@ensureBackgroundThread
|
return@ensureBackgroundThread
|
||||||
}
|
}
|
||||||
|
|
||||||
val listItems = storedItems.filter { it.name.contains(searchText, true) } as ArrayList<ListItem>
|
val listItems = storedItems.filter {
|
||||||
|
it.name.normalizeString().contains(searchNormalizedText, true)
|
||||||
|
} as ArrayList<ListItem>
|
||||||
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
getRecyclerAdapter()?.updateItems(listItems, text)
|
getRecyclerAdapter()?.updateItems(listItems, text)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import android.net.Uri
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.print.PrintAttributes
|
import android.print.PrintAttributes
|
||||||
import android.print.PrintManager
|
import android.print.PrintManager
|
||||||
|
import android.util.Base64
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.webkit.WebResourceRequest
|
import android.webkit.WebResourceRequest
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
@@ -143,6 +144,7 @@ class ReadTextActivity : SimpleActivity() {
|
|||||||
when (menuItem.itemId) {
|
when (menuItem.itemId) {
|
||||||
R.id.menu_search -> openSearch()
|
R.id.menu_search -> openSearch()
|
||||||
R.id.menu_save -> saveText()
|
R.id.menu_save -> saveText()
|
||||||
|
R.id.menu_save_as -> saveAsText()
|
||||||
R.id.menu_open_with -> openPath(intent.dataString!!, true)
|
R.id.menu_open_with -> openPath(intent.dataString!!, true)
|
||||||
R.id.menu_print -> printText()
|
R.id.menu_print -> printText()
|
||||||
else -> return@setOnMenuItemClickListener false
|
else -> return@setOnMenuItemClickListener false
|
||||||
@@ -164,10 +166,14 @@ class ReadTextActivity : SimpleActivity() {
|
|||||||
}, 250)
|
}, 250)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveText(shouldExitAfterSaving: Boolean = false) {
|
private fun updateFilePath() {
|
||||||
if (filePath.isEmpty()) {
|
if (filePath.isEmpty()) {
|
||||||
filePath = getRealPathFromURI(intent.data!!) ?: ""
|
filePath = getRealPathFromURI(intent.data!!) ?: ""
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveAsText(shouldExitAfterSaving: Boolean = false) {
|
||||||
|
updateFilePath()
|
||||||
|
|
||||||
if (filePath.isEmpty()) {
|
if (filePath.isEmpty()) {
|
||||||
SaveAsDialog(this, filePath, true) { _, filename ->
|
SaveAsDialog(this, filePath, true) { _, filename ->
|
||||||
@@ -181,6 +187,7 @@ class ReadTextActivity : SimpleActivity() {
|
|||||||
} else {
|
} else {
|
||||||
SELECT_SAVE_FILE_INTENT
|
SELECT_SAVE_FILE_INTENT
|
||||||
}
|
}
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
startActivityForResult(this, requestCode)
|
startActivityForResult(this, requestCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,6 +206,21 @@ class ReadTextActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun saveText(shouldExitAfterSaving: Boolean = false) {
|
||||||
|
updateFilePath()
|
||||||
|
|
||||||
|
if (filePath.isEmpty()) {
|
||||||
|
saveAsText(shouldExitAfterSaving)
|
||||||
|
} else if (hasStoragePermission()) {
|
||||||
|
val file = File(filePath)
|
||||||
|
getFileOutputStream(file.toFileDirItem(this), true) {
|
||||||
|
saveTextContent(it, shouldExitAfterSaving, true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toast(R.string.no_storage_permissions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun saveTextContent(outputStream: OutputStream?, shouldExitAfterSaving: Boolean, shouldOverwriteOriginalText: Boolean) {
|
private fun saveTextContent(outputStream: OutputStream?, shouldExitAfterSaving: Boolean, shouldOverwriteOriginalText: Boolean) {
|
||||||
if (outputStream != null) {
|
if (outputStream != null) {
|
||||||
val currentText = binding.readTextView.text.toString()
|
val currentText = binding.readTextView.text.toString()
|
||||||
@@ -229,7 +251,17 @@ class ReadTextActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
webView.loadData(binding.readTextView.text.toString(), "text/plain", "UTF-8")
|
val text = binding.readTextView.text.toString()
|
||||||
|
ensureBackgroundThread {
|
||||||
|
try {
|
||||||
|
val base64 = Base64.encodeToString(text.toByteArray(), Base64.DEFAULT)
|
||||||
|
runOnUiThread {
|
||||||
|
webView.loadData(base64, "text/plain", "base64")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
showErrorToast(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
showErrorToast(e)
|
showErrorToast(e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,21 @@ class SaveAsActivity : SimpleActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
tryInitFileManager()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun tryInitFileManager() {
|
||||||
|
handleStoragePermission { granted ->
|
||||||
|
if (granted) {
|
||||||
|
saveAsDialog()
|
||||||
|
} else {
|
||||||
|
toast(R.string.no_storage_permissions)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveAsDialog() {
|
||||||
if (intent.action == Intent.ACTION_SEND && intent.extras?.containsKey(Intent.EXTRA_STREAM) == true) {
|
if (intent.action == Intent.ACTION_SEND && intent.extras?.containsKey(Intent.EXTRA_STREAM) == true) {
|
||||||
FilePickerDialog(this, pickFile = false, showHidden = config.shouldShowHidden(), showFAB = true, showFavoritesButton = true) {
|
FilePickerDialog(this, pickFile = false, showHidden = config.shouldShowHidden(), showFAB = true, showFavoritesButton = true) {
|
||||||
val destination = it
|
val destination = it
|
||||||
@@ -36,8 +50,9 @@ class SaveAsActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val source = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)!!
|
val source = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)!!
|
||||||
val filename = getFilenameFromContentUri(source)
|
val originalFilename = getFilenameFromContentUri(source)
|
||||||
?: source.toString().getFilenameFromPath()
|
?: source.toString().getFilenameFromPath()
|
||||||
|
val filename = sanitizeFilename(originalFilename)
|
||||||
val mimeType = contentResolver.getType(source)
|
val mimeType = contentResolver.getType(source)
|
||||||
?: intent.type?.takeIf { it != "*/*" }
|
?: intent.type?.takeIf { it != "*/*" }
|
||||||
?: filename.getMimeType()
|
?: filename.getMimeType()
|
||||||
@@ -66,4 +81,9 @@ class SaveAsActivity : SimpleActivity() {
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
setupToolbar(binding.activitySaveAsToolbar, NavigationIcon.Arrow)
|
setupToolbar(binding.activitySaveAsToolbar, NavigationIcon.Arrow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun sanitizeFilename(filename: String): String {
|
||||||
|
return filename.replace("[/\\\\<>:\"|?*\u0000-\u001F]".toRegex(), "_")
|
||||||
|
.takeIf { it.isNotBlank() } ?: "unnamed_file"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
package org.fossify.filemanager.activities
|
package org.fossify.filemanager.activities
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
|
import android.provider.Settings
|
||||||
import org.fossify.commons.activities.BaseSimpleActivity
|
import org.fossify.commons.activities.BaseSimpleActivity
|
||||||
|
import org.fossify.commons.dialogs.ConfirmationAdvancedDialog
|
||||||
import org.fossify.commons.extensions.hasPermission
|
import org.fossify.commons.extensions.hasPermission
|
||||||
|
import android.net.Uri
|
||||||
|
import org.fossify.commons.extensions.showErrorToast
|
||||||
|
import org.fossify.commons.extensions.toast
|
||||||
import org.fossify.commons.helpers.PERMISSION_WRITE_STORAGE
|
import org.fossify.commons.helpers.PERMISSION_WRITE_STORAGE
|
||||||
import org.fossify.commons.helpers.isRPlus
|
import org.fossify.commons.helpers.isRPlus
|
||||||
import org.fossify.filemanager.R
|
import org.fossify.filemanager.R
|
||||||
@@ -31,10 +37,23 @@ open class SimpleActivity : BaseSimpleActivity() {
|
|||||||
R.mipmap.ic_launcher_grey_black
|
R.mipmap.ic_launcher_grey_black
|
||||||
)
|
)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val MANAGE_STORAGE_RC = 201
|
||||||
|
}
|
||||||
|
|
||||||
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
|
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
|
||||||
|
|
||||||
override fun getRepositoryName() = "File-Manager"
|
override fun getRepositoryName() = "File-Manager"
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, resultData)
|
||||||
|
isAskingPermissions = false
|
||||||
|
if (requestCode == MANAGE_STORAGE_RC && isRPlus()) {
|
||||||
|
actionOnPermission?.invoke(Environment.isExternalStorageManager())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
fun hasStoragePermission(): Boolean {
|
fun hasStoragePermission(): Boolean {
|
||||||
return if (isRPlus()) {
|
return if (isRPlus()) {
|
||||||
@@ -43,4 +62,39 @@ open class SimpleActivity : BaseSimpleActivity() {
|
|||||||
hasPermission(PERMISSION_WRITE_STORAGE)
|
hasPermission(PERMISSION_WRITE_STORAGE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("InlinedApi")
|
||||||
|
fun handleStoragePermission(callback: (granted: Boolean) -> Unit) {
|
||||||
|
actionOnPermission = null
|
||||||
|
if (hasStoragePermission()) {
|
||||||
|
callback(true)
|
||||||
|
} else {
|
||||||
|
if (isRPlus()) {
|
||||||
|
ConfirmationAdvancedDialog(this, "", R.string.access_storage_prompt, R.string.ok, 0, false) { success ->
|
||||||
|
if (success) {
|
||||||
|
isAskingPermissions = true
|
||||||
|
actionOnPermission = callback
|
||||||
|
try {
|
||||||
|
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
|
||||||
|
intent.addCategory("android.intent.category.DEFAULT")
|
||||||
|
intent.data = Uri.parse("package:$packageName")
|
||||||
|
startActivityForResult(intent, MANAGE_STORAGE_RC)
|
||||||
|
} catch (e: android.content.ActivityNotFoundException) {
|
||||||
|
showErrorToast(e)
|
||||||
|
val intent = Intent()
|
||||||
|
intent.action = Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
|
||||||
|
startActivityForResult(intent, MANAGE_STORAGE_RC)
|
||||||
|
} catch (e: SecurityException) {
|
||||||
|
showErrorToast(e)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handlePermission(PERMISSION_WRITE_STORAGE, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ class ItemsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerF
|
|||||||
}
|
}
|
||||||
|
|
||||||
var lastModified = lastModifieds.remove(curPath)
|
var lastModified = lastModifieds.remove(curPath)
|
||||||
val isDirectory = if (lastModified != null) false else file.isDirectory
|
val isDirectory = file.isDirectory
|
||||||
val children = if (isDirectory && getProperChildCount) file.getDirectChildrenCount(context, showHidden) else 0
|
val children = if (isDirectory && getProperChildCount) file.getDirectChildrenCount(context, showHidden) else 0
|
||||||
val size = if (isDirectory) {
|
val size = if (isDirectory) {
|
||||||
if (isSortingBySize) {
|
if (isSortingBySize) {
|
||||||
@@ -377,6 +377,7 @@ class ItemsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerF
|
|||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val normalizedText = text.normalizeString()
|
||||||
val sorting = context!!.config.getFolderSorting(path)
|
val sorting = context!!.config.getFolderSorting(path)
|
||||||
FileDirItem.sorting = context!!.config.getFolderSorting(currentPath)
|
FileDirItem.sorting = context!!.config.getFolderSorting(currentPath)
|
||||||
val isSortingBySize = sorting and SORT_BY_SIZE != 0
|
val isSortingBySize = sorting and SORT_BY_SIZE != 0
|
||||||
@@ -386,7 +387,7 @@ class ItemsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerF
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (it.isDirectory) {
|
if (it.isDirectory) {
|
||||||
if (it.name.contains(text, true)) {
|
if (it.name.normalizeString().contains(normalizedText, true)) {
|
||||||
val fileDirItem = getListItemFromFile(it, isSortingBySize, HashMap(), false)
|
val fileDirItem = getListItemFromFile(it, isSortingBySize, HashMap(), false)
|
||||||
if (fileDirItem != null) {
|
if (fileDirItem != null) {
|
||||||
files.add(fileDirItem)
|
files.add(fileDirItem)
|
||||||
@@ -395,7 +396,7 @@ class ItemsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerF
|
|||||||
|
|
||||||
files.addAll(searchFiles(text, it.absolutePath))
|
files.addAll(searchFiles(text, it.absolutePath))
|
||||||
} else {
|
} else {
|
||||||
if (it.name.contains(text, true)) {
|
if (it.name.normalizeString().contains(normalizedText, true)) {
|
||||||
val fileDirItem = getListItemFromFile(it, isSortingBySize, HashMap(), false)
|
val fileDirItem = getListItemFromFile(it, isSortingBySize, HashMap(), false)
|
||||||
if (fileDirItem != null) {
|
if (fileDirItem != null) {
|
||||||
files.add(fileDirItem)
|
files.add(fileDirItem)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.fossify.commons.extensions.getDoesFilePathExist
|
|||||||
import org.fossify.commons.extensions.getFilenameFromPath
|
import org.fossify.commons.extensions.getFilenameFromPath
|
||||||
import org.fossify.commons.extensions.getLongValue
|
import org.fossify.commons.extensions.getLongValue
|
||||||
import org.fossify.commons.extensions.getStringValue
|
import org.fossify.commons.extensions.getStringValue
|
||||||
|
import org.fossify.commons.extensions.normalizeString
|
||||||
import org.fossify.commons.extensions.showErrorToast
|
import org.fossify.commons.extensions.showErrorToast
|
||||||
import org.fossify.commons.helpers.VIEW_TYPE_GRID
|
import org.fossify.commons.helpers.VIEW_TYPE_GRID
|
||||||
import org.fossify.commons.helpers.VIEW_TYPE_LIST
|
import org.fossify.commons.helpers.VIEW_TYPE_LIST
|
||||||
@@ -178,9 +179,11 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
val name = cursor.getStringValue(FileColumns.DISPLAY_NAME) ?: path.getFilenameFromPath()
|
val name = cursor.getStringValue(FileColumns.DISPLAY_NAME) ?: path.getFilenameFromPath()
|
||||||
val size = cursor.getLongValue(FileColumns.SIZE)
|
val size = cursor.getLongValue(FileColumns.SIZE)
|
||||||
val modified = cursor.getLongValue(FileColumns.DATE_MODIFIED) * 1000
|
val modified = cursor.getLongValue(FileColumns.DATE_MODIFIED) * 1000
|
||||||
val fileDirItem = ListItem(path, name, false, 0, size, modified, false, false)
|
val isHiddenFile = name.startsWith(".")
|
||||||
if ((showHidden || !name.startsWith(".")) && activity?.getDoesFilePathExist(path) == true) {
|
val shouldShow = showHidden || (!isHiddenFile && !isPathInHiddenFolder(path))
|
||||||
|
if (shouldShow && activity?.getDoesFilePathExist(path) == true) {
|
||||||
if (wantedMimeTypes.any { isProperMimeType(it, path, false) }) {
|
if (wantedMimeTypes.any { isProperMimeType(it, path, false) }) {
|
||||||
|
val fileDirItem = ListItem(path, name, false, 0, size, modified, false, false)
|
||||||
listItems.add(fileDirItem)
|
listItems.add(fileDirItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,6 +199,18 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isPathInHiddenFolder(path: String): Boolean {
|
||||||
|
val parts = path.split("/")
|
||||||
|
for (i in 1 until parts.size - 1) {
|
||||||
|
val part = parts[i]
|
||||||
|
val isHidden = part.startsWith(".") && part != "." && part != ".." && part.isNotEmpty()
|
||||||
|
if (isHidden) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private fun getRecyclerAdapter() = binding.recentsList.adapter as? ItemsAdapter
|
private fun getRecyclerAdapter() = binding.recentsList.adapter as? ItemsAdapter
|
||||||
|
|
||||||
override fun toggleFilenameVisibility() {
|
override fun toggleFilenameVisibility() {
|
||||||
@@ -242,7 +257,11 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
|
|
||||||
override fun searchQueryChanged(text: String) {
|
override fun searchQueryChanged(text: String) {
|
||||||
lastSearchedText = text
|
lastSearchedText = text
|
||||||
val filtered = filesIgnoringSearch.filter { it.mName.contains(text, true) }.toMutableList() as ArrayList<ListItem>
|
val normalizedText = text.normalizeString()
|
||||||
|
val filtered = filesIgnoringSearch.filter {
|
||||||
|
it.mName.normalizeString().contains(normalizedText, true)
|
||||||
|
}.toMutableList() as ArrayList<ListItem>
|
||||||
|
|
||||||
binding.apply {
|
binding.apply {
|
||||||
(recentsList.adapter as? ItemsAdapter)?.updateItems(filtered, text)
|
(recentsList.adapter as? ItemsAdapter)?.updateItems(filtered, text)
|
||||||
recentsPlaceholder.beVisibleIf(filtered.isEmpty())
|
recentsPlaceholder.beVisibleIf(filtered.isEmpty())
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.fossify.commons.extensions.getLongValue
|
|||||||
import org.fossify.commons.extensions.getProperBackgroundColor
|
import org.fossify.commons.extensions.getProperBackgroundColor
|
||||||
import org.fossify.commons.extensions.getProperPrimaryColor
|
import org.fossify.commons.extensions.getProperPrimaryColor
|
||||||
import org.fossify.commons.extensions.getStringValue
|
import org.fossify.commons.extensions.getStringValue
|
||||||
|
import org.fossify.commons.extensions.normalizeString
|
||||||
import org.fossify.commons.extensions.queryCursor
|
import org.fossify.commons.extensions.queryCursor
|
||||||
import org.fossify.commons.extensions.showErrorToast
|
import org.fossify.commons.extensions.showErrorToast
|
||||||
import org.fossify.commons.extensions.updateTextColors
|
import org.fossify.commons.extensions.updateTextColors
|
||||||
@@ -340,6 +341,7 @@ class StorageFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun searchQueryChanged(text: String) {
|
override fun searchQueryChanged(text: String) {
|
||||||
|
val normalizedText = text.normalizeString()
|
||||||
lastSearchedText = text
|
lastSearchedText = text
|
||||||
binding.apply {
|
binding.apply {
|
||||||
if (text.isNotEmpty()) {
|
if (text.isNotEmpty()) {
|
||||||
@@ -364,7 +366,10 @@ class StorageFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
} else {
|
} else {
|
||||||
showProgressBar()
|
showProgressBar()
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val filtered = allDeviceListItems.filter { it.mName.contains(text, true) }.toMutableList() as ArrayList<ListItem>
|
val filtered = allDeviceListItems.filter {
|
||||||
|
it.mName.normalizeString().contains(normalizedText, true)
|
||||||
|
}.toMutableList() as ArrayList<ListItem>
|
||||||
|
|
||||||
if (lastSearchedText != text) {
|
if (lastSearchedText != text) {
|
||||||
return@ensureBackgroundThread
|
return@ensureBackgroundThread
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,13 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/menu_save"
|
android:id="@+id/menu_save"
|
||||||
android:icon="@drawable/ic_save_vector"
|
android:icon="@drawable/ic_save_vector"
|
||||||
android:title="@string/save_as"
|
android:title="@string/save"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_save_as"
|
||||||
|
android:showAsAction="never"
|
||||||
|
android:title="@string/save_as"
|
||||||
|
app:showAsAction="never" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_print"
|
android:id="@+id/menu_print"
|
||||||
android:icon="@drawable/ic_print_vector"
|
android:icon="@drawable/ic_print_vector"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<string name="path_copied">Bane kopiert</string>
|
<string name="path_copied">Bane kopiert</string>
|
||||||
<string name="select_audio_file">Vennligst velg en lydfil</string>
|
<string name="select_audio_file">Vennligst velg en lydfil</string>
|
||||||
<string name="search_folder">Søk etter mappe</string>
|
<string name="search_folder">Søk etter mappe</string>
|
||||||
<string name="rooted_device_only">Denne handlingen fungerer bare på rootede enheter.</string>
|
<string name="rooted_device_only">Denne handlingen fungerer bare på enheter med rot-tilgang</string>
|
||||||
<string name="recents">Nylige</string>
|
<string name="recents">Nylige</string>
|
||||||
<string name="show_recents">Vis nylige</string>
|
<string name="show_recents">Vis nylige</string>
|
||||||
<string name="open_as">Åpne som</string>
|
<string name="open_as">Åpne som</string>
|
||||||
@@ -40,4 +40,8 @@
|
|||||||
<string name="storage_free">ledig</string>
|
<string name="storage_free">ledig</string>
|
||||||
<string name="total_storage">Total lagring: %s</string>
|
<string name="total_storage">Total lagring: %s</string>
|
||||||
<string name="enable_root_access">Aktiver root-tilgang</string>
|
<string name="enable_root_access">Aktiver root-tilgang</string>
|
||||||
|
<string name="invert_colors">Inverter farger</string>
|
||||||
|
<string name="storage_analysis">Lagringsanalyse</string>
|
||||||
|
<string name="others">Andre</string>
|
||||||
|
<string name="press_back_twice">Trykk Tilbake to ganger for å avslutte appen</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_launcher_name">Филе Манагер</string>
|
<string name="app_launcher_name">Менаџер фајлова</string>
|
||||||
<string name="press_back_again">Притисните поново да бисте изашли</string>
|
<string name="press_back_again">Притисните поново да бисте изашли</string>
|
||||||
<string name="go_to_home_folder">Идите у почетни фолдер</string>
|
<string name="go_to_home_folder">Идите у почетни фолдер</string>
|
||||||
<string name="set_as_home_folder">Постави као почетни фолдер</string>
|
<string name="set_as_home_folder">Постави као почетни фолдер</string>
|
||||||
|
|||||||
@@ -1,4 +1,47 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="images">圖片</string>
|
<string name="images">圖片</string>
|
||||||
</resources>
|
<string name="videos">影片</string>
|
||||||
|
<string name="app_launcher_name">檔案管理器</string>
|
||||||
|
<string name="press_back_again">再按一次返回以離開</string>
|
||||||
|
<string name="go_to_home_folder">前往主資料夾</string>
|
||||||
|
<string name="set_as_home_folder">設為主資料夾</string>
|
||||||
|
<string name="home_folder_updated">主資料夾已更新</string>
|
||||||
|
<string name="copy_path">路徑複製到剪貼簿</string>
|
||||||
|
<string name="path_copied">路徑已複製</string>
|
||||||
|
<string name="select_audio_file">請選擇一個音訊檔案</string>
|
||||||
|
<string name="search_folder">搜尋資料夾</string>
|
||||||
|
<string name="rooted_device_only">這個操作只對已 root 的裝置有用</string>
|
||||||
|
<string name="recents">最近瀏覽</string>
|
||||||
|
<string name="show_recents">顯示最近瀏覽</string>
|
||||||
|
<string name="invert_colors">顏色反轉</string>
|
||||||
|
<string name="open_as">開啟為</string>
|
||||||
|
<string name="text_file">文字檔案</string>
|
||||||
|
<string name="image_file">圖片檔案</string>
|
||||||
|
<string name="audio_file">音源檔案</string>
|
||||||
|
<string name="video_file">影片檔案</string>
|
||||||
|
<string name="other_file">其他檔案</string>
|
||||||
|
<string name="compress">壓縮</string>
|
||||||
|
<string name="decompress">解壓縮</string>
|
||||||
|
<string name="compress_as">壓縮為</string>
|
||||||
|
<string name="compressing">壓縮中…</string>
|
||||||
|
<string name="decompressing">解壓縮中…</string>
|
||||||
|
<string name="compression_successful">壓縮成功</string>
|
||||||
|
<string name="decompression_successful">解壓縮成功</string>
|
||||||
|
<string name="compressing_failed">壓縮失敗</string>
|
||||||
|
<string name="decompressing_failed">解壓縮失敗</string>
|
||||||
|
<string name="manage_favorites">管理我的最愛</string>
|
||||||
|
<string name="go_to_favorite">前往我的最愛</string>
|
||||||
|
<string name="favorites_activity_placeholder">你可將常用資料夾加入我的最愛,方便從任何地方開啟。</string>
|
||||||
|
<string name="file_editor">檔案編輯器</string>
|
||||||
|
<string name="storage_analysis">儲存空間分析</string>
|
||||||
|
<string name="audio">音訊</string>
|
||||||
|
<string name="documents">文件</string>
|
||||||
|
<string name="downloads">下載</string>
|
||||||
|
<string name="archives">封存</string>
|
||||||
|
<string name="others">其他</string>
|
||||||
|
<string name="storage_free">可用空間</string>
|
||||||
|
<string name="total_storage">總儲存空間:%s</string>
|
||||||
|
<string name="enable_root_access">啟用 root 權限</string>
|
||||||
|
<string name="press_back_twice">需按兩次返回鍵才能離開 app</string>
|
||||||
|
</resources>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_launcher_name">簡易檔案管理器</string>
|
<string name="app_launcher_name">檔案管理器</string>
|
||||||
<string name="press_back_again">再按一次返回以離開</string>
|
<string name="press_back_again">再按一次返回以離開</string>
|
||||||
<string name="go_to_home_folder">前往主資料夾</string>
|
<string name="go_to_home_folder">前往主資料夾</string>
|
||||||
<string name="set_as_home_folder">設為主資料夾</string>
|
<string name="set_as_home_folder">設為主資料夾</string>
|
||||||
@@ -44,4 +44,4 @@
|
|||||||
<string name="show_recents">顯示最近造訪</string>
|
<string name="show_recents">顯示最近造訪</string>
|
||||||
<string name="documents">文件</string>
|
<string name="documents">文件</string>
|
||||||
<string name="storage_free">可用空間</string>
|
<string name="storage_free">可用空間</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Fixed:
|
||||||
|
|
||||||
|
• Fixed folders showing up incorrectly as files in some cases
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
Added:
|
||||||
|
|
||||||
|
• Added a separate "Save as" option in the text editor
|
||||||
|
|
||||||
|
Changed:
|
||||||
|
|
||||||
|
• Save button now overwrites files directly in the text editor
|
||||||
|
• Search now ignores accents and diacritics
|
||||||
|
• Updated translations
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
|
||||||
|
• Fixed folders showing up incorrectly as files in the copy/move dialog
|
||||||
|
• Fixed error when saving files with unsupported characters
|
||||||
|
• Fixed printing text files containing a "#"
|
||||||
|
• Fixed files in hidden folders showing up in the recent tab
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
厭倦了檔案管理器會拖慢您的速度並侵犯您的私私嗎?使用 Fossify File Manager 解鎖閃電般快速、安全且完全可自訂的體驗。 ⚡
|
||||||
|
|
||||||
|
🚀 以極快的導航統治您的數位世界:
|
||||||
|
• 透過簡單的壓縮和傳輸功能快速管理您的檔案,讓您的數位生活井然有序。
|
||||||
|
• 使用可自訂的主資料夾和我的最愛捷徑快速存取最常用的資料夾。
|
||||||
|
• 透過直觀的導航、搜尋和排序選項,在幾秒鐘內找到您需要的內容。
|
||||||
|
|
||||||
|
🔐 以無與倫比的私隱和安全性強化您的資料:
|
||||||
|
• 使用密碼、圖案或指紋鎖定保護敏感檔案的隱藏項目或整個應用程式。
|
||||||
|
• 無需網絡連線-您的檔案在您的裝置上保持私密且安全。
|
||||||
|
|
||||||
|
💾 像專業人士一樣掌控您的儲存:
|
||||||
|
• 透過輕鬆的檔案和資料夾壓縮來清理空間,以最大限度地發揮設備的潛力。
|
||||||
|
• 使用內建儲存分析工具辨識並清理佔用空間的檔案。
|
||||||
|
• 無縫導航根檔案、SD 卡和 USB 裝置以實現整體組織。
|
||||||
|
|
||||||
|
📁 使用便利工具優化您的工作流程:
|
||||||
|
• 建立桌面捷徑以即時存取最常用的檔案和資料夾。
|
||||||
|
• 使用輕量級檔案編輯器輕鬆編輯、列印或閱讀文件,並透過縮放手勢進行增強。
|
||||||
|
|
||||||
|
🌈 透過無限的客製化打造您自己的:
|
||||||
|
• 享受無廣告、開源體驗,讓您而非企業巨頭掌控一切。
|
||||||
|
• 個人化顏色、主題和圖示以反映您獨特的風格和偏好。
|
||||||
|
|
||||||
|
拋棄臃腫、侵犯私隱的檔案管理器,使用 Fossify File Manager 體驗真正的自由。立即下載並重新掌控您的數位生活!
|
||||||
|
|
||||||
|
探索 Fossify 的更多應用程式:https://www.fossify.org
|
||||||
|
原始碼:https://www.github.com/FossifyOrg
|
||||||
|
加入 Reddit 社群:https://www.reddit.com/r/Fossify
|
||||||
|
在 Telegram 上連接:https://t.me/Fossify
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
具備基本功能的輕便好用開源檔案管理器。
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
厭倦了檔案管理器會拖慢您的速度並侵犯您的隱私嗎?使用 Fossify File Manager 解鎖閃電般快速、安全且完全可自訂的體驗。 ⚡
|
||||||
|
|
||||||
|
🚀 以極快的導航統治您的數位世界:
|
||||||
|
• 透過簡單的壓縮和傳輸功能快速管理您的檔案,讓您的數位生活井井有條。
|
||||||
|
• 使用可自訂的主資料夾和最喜愛的捷徑快速存取最常用的資料夾。
|
||||||
|
• 透過直覺的導航、搜尋和排序選項,在幾秒鐘內找到您需要的內容。
|
||||||
|
|
||||||
|
🔐 以無與倫比的隱私和安全性強化您的資料:
|
||||||
|
• 使用密碼、圖案或指紋鎖定保護敏感檔案的隱藏項目或整個應用程式。
|
||||||
|
• 無需上網-您的檔案在您的裝置上保持私密且安全。
|
||||||
|
|
||||||
|
💾 像專業人士一樣掌控您的儲存:
|
||||||
|
• 透過輕鬆的檔案和資料夾壓縮來清理空間,以最大限度地發揮設備的潛力。
|
||||||
|
• 使用內建儲存分析工具辨識並清理佔用空間的檔案。
|
||||||
|
• 無縫導航根檔案、SD 卡和 USB 裝置以實現整體組織。
|
||||||
|
|
||||||
|
📁 使用便利工具優化您的工作流程:
|
||||||
|
• 建立桌面捷徑以即時存取最常用的檔案和資料夾。
|
||||||
|
• 使用輕量級檔案編輯器輕鬆編輯、列印或閱讀文檔,並透過縮放手勢進行增強。
|
||||||
|
|
||||||
|
🌈 透過無限的客製化打造您自己的:
|
||||||
|
• 享受無廣告、開源體驗,讓您而非企業巨頭掌控一切。
|
||||||
|
• 個人化顏色、主題和圖示以反映您獨特的風格和偏好。
|
||||||
|
|
||||||
|
拋棄臃腫、侵犯隱私的檔案管理器,使用 Fossify File Manager 體驗真正的自由。立即下載並重新掌控您的數位生活!
|
||||||
|
|
||||||
|
探索 Fossify 的更多應用程式:https://www.fossify.org
|
||||||
|
原始碼:https://www.github.com/FossifyOrg
|
||||||
|
加入 Reddit 社群:https://www.reddit.com/r/Fossify
|
||||||
|
在 Telegram 上連接:https://t.me/Fossify
|
||||||
+2
-2
@@ -20,6 +20,6 @@ org.gradle.jvmargs=-Xmx4g
|
|||||||
# org.gradle.parallel=true
|
# org.gradle.parallel=true
|
||||||
|
|
||||||
# Versioning
|
# Versioning
|
||||||
VERSION_NAME=1.2.2
|
VERSION_NAME=1.3.0
|
||||||
VERSION_CODE=6
|
VERSION_CODE=8
|
||||||
APP_ID=org.fossify.filemanager
|
APP_ID=org.fossify.filemanager
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[versions]
|
[versions]
|
||||||
#jetbrains
|
#jetbrains
|
||||||
kotlin = "2.2.10"
|
kotlin = "2.2.20"
|
||||||
#Detekt
|
#Detekt
|
||||||
detekt = "1.23.8"
|
detekt = "1.23.8"
|
||||||
detektCompose = "0.4.27"
|
detektCompose = "0.4.27"
|
||||||
@@ -8,7 +8,7 @@ detektCompose = "0.4.27"
|
|||||||
androidx-swiperefreshlayout = "1.1.0"
|
androidx-swiperefreshlayout = "1.1.0"
|
||||||
androidx-documentfile = "1.1.0"
|
androidx-documentfile = "1.1.0"
|
||||||
#Fossify
|
#Fossify
|
||||||
commons = "5.0.2"
|
commons = "5.2.0"
|
||||||
#Other
|
#Other
|
||||||
autofittextview = "0.2.1"
|
autofittextview = "0.2.1"
|
||||||
gestureviews = "2.8.3"
|
gestureviews = "2.8.3"
|
||||||
|
|||||||
Reference in new issue
Block a user