Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
fca630954e |
@ -9,8 +9,6 @@ import android.system.Os
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import sushi.hardcore.droidfs.filesystems.EncryptedVolume
|
import sushi.hardcore.droidfs.filesystems.EncryptedVolume
|
||||||
import sushi.hardcore.droidfs.util.Compat
|
import sushi.hardcore.droidfs.util.Compat
|
||||||
@ -88,11 +86,9 @@ class EncryptedFileProvider(context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun free() {
|
override fun free() {
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
|
||||||
Wiper.wipe(file)
|
Wiper.wipe(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class ExportedMemFile private constructor(path: String, private val file: MemFile) :
|
class ExportedMemFile private constructor(path: String, private val file: MemFile) :
|
||||||
ExportedFile(path) {
|
ExportedFile(path) {
|
||||||
@ -164,10 +160,8 @@ class EncryptedFileProvider(context: Context) {
|
|||||||
exportedFile: ExportedFile,
|
exportedFile: ExportedFile,
|
||||||
encryptedVolume: EncryptedVolume,
|
encryptedVolume: EncryptedVolume,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val pfd = exportedFile.open(ParcelFileDescriptor.MODE_WRITE_ONLY, false)
|
val fd = exportedFile.open(ParcelFileDescriptor.MODE_WRITE_ONLY, false).fileDescriptor
|
||||||
return encryptedVolume.exportFile(exportedFile.path, FileOutputStream(pfd.fileDescriptor)).also {
|
return encryptedVolume.exportFile(exportedFile.path, FileOutputStream(fd))
|
||||||
pfd.close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Error {
|
enum class Error {
|
||||||
|
@ -4,8 +4,8 @@ import java.io.File
|
|||||||
|
|
||||||
object FileTypes {
|
object FileTypes {
|
||||||
private val FILE_EXTENSIONS = mapOf(
|
private val FILE_EXTENSIONS = mapOf(
|
||||||
Pair("image", listOf("png", "jpg", "jpeg", "gif", "avif", "webp", "bmp", "heic")),
|
Pair("image", listOf("png", "jpg", "jpeg", "gif", "webp", "bmp", "heic")),
|
||||||
Pair("video", listOf("mp4", "webm", "mkv", "mov", "m4v")),
|
Pair("video", listOf("mp4", "webm", "mkv", "mov")),
|
||||||
Pair("audio", listOf("mp3", "ogg", "m4a", "wav", "flac", "opus")),
|
Pair("audio", listOf("mp3", "ogg", "m4a", "wav", "flac", "opus")),
|
||||||
Pair("pdf", listOf("pdf")),
|
Pair("pdf", listOf("pdf")),
|
||||||
Pair("text", listOf(
|
Pair("text", listOf(
|
||||||
|
@ -328,8 +328,8 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
activityScope.launch {
|
activityScope.launch {
|
||||||
onTaskResult(
|
onTaskResult(
|
||||||
fileOperationService.moveElements(volumeId, toMove, toClean),
|
fileOperationService.moveElements(volumeId, toMove, toClean),
|
||||||
R.string.move_failed,
|
|
||||||
R.string.move_success,
|
R.string.move_success,
|
||||||
|
R.string.move_failed,
|
||||||
)
|
)
|
||||||
setCurrentPath(currentDirectoryPath)
|
setCurrentPath(currentDirectoryPath)
|
||||||
}
|
}
|
||||||
|
@ -104,9 +104,7 @@ class FileOperationService : Service() {
|
|||||||
activity.lifecycle.addObserver(object : DefaultLifecycleObserver {
|
activity.lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||||
override fun onDestroy(owner: LifecycleOwner) {
|
override fun onDestroy(owner: LifecycleOwner) {
|
||||||
activity.unbindService(serviceConnection)
|
activity.unbindService(serviceConnection)
|
||||||
// Could have been more efficient with a LinkedHashMap but the JDK implementation doesn't allow
|
service.notificationPermissionHelpers.removeLast()
|
||||||
// to access the latest element in O(1) unless using reflection
|
|
||||||
service.notificationPermissionHelpers.removeAll { it.activity == activity }
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
activity.bindService(
|
activity.bindService(
|
||||||
|
@ -14,8 +14,6 @@ import androidx.lifecycle.lifecycleScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.sync.Mutex
|
|
||||||
import kotlinx.coroutines.sync.withLock
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import sushi.hardcore.droidfs.BaseActivity
|
import sushi.hardcore.droidfs.BaseActivity
|
||||||
import sushi.hardcore.droidfs.FileTypes
|
import sushi.hardcore.droidfs.FileTypes
|
||||||
@ -23,6 +21,7 @@ import sushi.hardcore.droidfs.R
|
|||||||
import sushi.hardcore.droidfs.VolumeManagerApp
|
import sushi.hardcore.droidfs.VolumeManagerApp
|
||||||
import sushi.hardcore.droidfs.explorers.ExplorerElement
|
import sushi.hardcore.droidfs.explorers.ExplorerElement
|
||||||
import sushi.hardcore.droidfs.filesystems.EncryptedVolume
|
import sushi.hardcore.droidfs.filesystems.EncryptedVolume
|
||||||
|
import sushi.hardcore.droidfs.util.IntentUtils
|
||||||
import sushi.hardcore.droidfs.util.PathUtils
|
import sushi.hardcore.droidfs.util.PathUtils
|
||||||
import sushi.hardcore.droidfs.util.finishOnClose
|
import sushi.hardcore.droidfs.util.finishOnClose
|
||||||
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
|
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
|
||||||
@ -33,8 +32,9 @@ abstract class FileViewerActivity: BaseActivity() {
|
|||||||
private lateinit var originalParentPath: String
|
private lateinit var originalParentPath: String
|
||||||
private lateinit var windowInsetsController: WindowInsetsControllerCompat
|
private lateinit var windowInsetsController: WindowInsetsControllerCompat
|
||||||
private var windowTypeMask = 0
|
private var windowTypeMask = 0
|
||||||
protected val playlist = mutableListOf<ExplorerElement>()
|
private var foldersFirst = true
|
||||||
private val playlistMutex = Mutex()
|
private var wasMapped = false
|
||||||
|
protected val mappedPlaylist = mutableListOf<ExplorerElement>()
|
||||||
protected var currentPlaylistIndex = -1
|
protected var currentPlaylistIndex = -1
|
||||||
private val isLegacyFullscreen = Build.VERSION.SDK_INT <= Build.VERSION_CODES.R
|
private val isLegacyFullscreen = Build.VERSION.SDK_INT <= Build.VERSION_CODES.R
|
||||||
|
|
||||||
@ -46,6 +46,7 @@ abstract class FileViewerActivity: BaseActivity() {
|
|||||||
intent.getIntExtra("volumeId", -1)
|
intent.getIntExtra("volumeId", -1)
|
||||||
)!!
|
)!!
|
||||||
finishOnClose(encryptedVolume)
|
finishOnClose(encryptedVolume)
|
||||||
|
foldersFirst = sharedPrefs.getBoolean("folders_first", true)
|
||||||
windowInsetsController = WindowInsetsControllerCompat(window, window.decorView)
|
windowInsetsController = WindowInsetsControllerCompat(window, window.decorView)
|
||||||
windowInsetsController.addOnControllableInsetsChangedListener { _, typeMask ->
|
windowInsetsController.addOnControllableInsetsChangedListener { _, typeMask ->
|
||||||
windowTypeMask = typeMask
|
windowTypeMask = typeMask
|
||||||
@ -130,57 +131,48 @@ abstract class FileViewerActivity: BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected suspend fun createPlaylist() {
|
protected fun createPlaylist() {
|
||||||
playlistMutex.withLock {
|
if (!wasMapped){
|
||||||
if (currentPlaylistIndex != -1) {
|
encryptedVolume.recursiveMapFiles(originalParentPath)?.let { elements ->
|
||||||
// playlist already initialized
|
for (e in elements) {
|
||||||
return
|
if (e.isRegularFile) {
|
||||||
|
if (FileTypes.isExtensionType(getFileType(), e.name) || filePath == e.fullPath) {
|
||||||
|
mappedPlaylist.add(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
if (sharedPrefs.getBoolean("map_folders", true)) {
|
|
||||||
encryptedVolume.recursiveMapFiles(originalParentPath)
|
|
||||||
} else {
|
|
||||||
encryptedVolume.readDir(originalParentPath)
|
|
||||||
}?.filterTo(playlist) { e ->
|
|
||||||
e.isRegularFile && (FileTypes.isExtensionType(getFileType(), e.name) || filePath == e.fullPath)
|
|
||||||
}
|
}
|
||||||
val sortOrder = intent.getStringExtra("sortOrder") ?: "name"
|
val sortOrder = intent.getStringExtra("sortOrder") ?: "name"
|
||||||
val foldersFirst = sharedPrefs.getBoolean("folders_first", true)
|
ExplorerElement.sortBy(sortOrder, foldersFirst, mappedPlaylist)
|
||||||
ExplorerElement.sortBy(sortOrder, foldersFirst, playlist)
|
//find current index
|
||||||
currentPlaylistIndex = playlist.indexOfFirst { it.fullPath == filePath }
|
for ((i, e) in mappedPlaylist.withIndex()){
|
||||||
|
if (filePath == e.fullPath){
|
||||||
|
currentPlaylistIndex = i
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
wasMapped = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateCurrentItem() {
|
protected fun playlistNext(forward: Boolean) {
|
||||||
filePath = playlist[currentPlaylistIndex].fullPath
|
|
||||||
}
|
|
||||||
|
|
||||||
protected suspend fun playlistNext(forward: Boolean) {
|
|
||||||
createPlaylist()
|
createPlaylist()
|
||||||
currentPlaylistIndex = if (forward) {
|
currentPlaylistIndex = if (forward) {
|
||||||
(currentPlaylistIndex + 1).mod(playlist.size)
|
(currentPlaylistIndex+1)%mappedPlaylist.size
|
||||||
} else {
|
} else {
|
||||||
(currentPlaylistIndex - 1).mod(playlist.size)
|
var x = (currentPlaylistIndex-1)%mappedPlaylist.size
|
||||||
|
if (x < 0) {
|
||||||
|
x += mappedPlaylist.size
|
||||||
}
|
}
|
||||||
updateCurrentItem()
|
x
|
||||||
|
}
|
||||||
|
filePath = mappedPlaylist[currentPlaylistIndex].fullPath
|
||||||
}
|
}
|
||||||
|
|
||||||
protected suspend fun deleteCurrentFile(): Boolean {
|
protected fun refreshPlaylist() {
|
||||||
createPlaylist() // ensure we know the current position in the playlist
|
mappedPlaylist.clear()
|
||||||
return if (encryptedVolume.deleteFile(filePath)) {
|
wasMapped = false
|
||||||
playlist.removeAt(currentPlaylistIndex)
|
createPlaylist()
|
||||||
if (playlist.size != 0) {
|
|
||||||
if (currentPlaylistIndex == playlist.size) {
|
|
||||||
// deleted the last element of the playlist, go back to the first
|
|
||||||
currentPlaylistIndex = 0
|
|
||||||
}
|
|
||||||
updateCurrentItem()
|
|
||||||
}
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun goBackToExplorer() {
|
protected fun goBackToExplorer() {
|
||||||
|
@ -12,12 +12,10 @@ import android.widget.Toast
|
|||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.RequestBuilder
|
import com.bumptech.glide.RequestBuilder
|
||||||
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
|
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
|
||||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import sushi.hardcore.droidfs.Constants
|
import sushi.hardcore.droidfs.Constants
|
||||||
import sushi.hardcore.droidfs.R
|
import sushi.hardcore.droidfs.R
|
||||||
import sushi.hardcore.droidfs.databinding.ActivityImageViewerBinding
|
import sushi.hardcore.droidfs.databinding.ActivityImageViewerBinding
|
||||||
@ -107,15 +105,17 @@ class ImageViewer: FileViewerActivity() {
|
|||||||
.keepFullScreen()
|
.keepFullScreen()
|
||||||
.setTitle(R.string.warning)
|
.setTitle(R.string.warning)
|
||||||
.setPositiveButton(R.string.ok) { _, _ ->
|
.setPositiveButton(R.string.ok) { _, _ ->
|
||||||
lifecycleScope.launch {
|
createPlaylist() //be sure the playlist is created before deleting if there is only one image
|
||||||
if (deleteCurrentFile()) {
|
if (encryptedVolume.deleteFile(filePath)) {
|
||||||
if (playlist.size == 0) { // no more image left
|
playlistNext(true)
|
||||||
|
refreshPlaylist()
|
||||||
|
if (mappedPlaylist.size == 0) { //deleted all images of the playlist
|
||||||
goBackToExplorer()
|
goBackToExplorer()
|
||||||
} else {
|
} else {
|
||||||
loadImage(true)
|
loadImage(true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CustomAlertDialogBuilder(this@ImageViewer, theme)
|
CustomAlertDialogBuilder(this, theme)
|
||||||
.keepFullScreen()
|
.keepFullScreen()
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setMessage(getString(R.string.remove_failed, fileName))
|
.setMessage(getString(R.string.remove_failed, fileName))
|
||||||
@ -123,7 +123,6 @@ class ImageViewer: FileViewerActivity() {
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
.setMessage(getString(R.string.single_delete_confirm, fileName))
|
.setMessage(getString(R.string.single_delete_confirm, fileName))
|
||||||
.show()
|
.show()
|
||||||
@ -199,18 +198,16 @@ class ImageViewer: FileViewerActivity() {
|
|||||||
rotateImage()
|
rotateImage()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun swipeImage(deltaX: Float, slideshowSwipe: Boolean = false) {
|
private fun swipeImage(deltaX: Float, slideshowSwipe: Boolean = false){
|
||||||
lifecycleScope.launch {
|
|
||||||
playlistNext(deltaX < 0)
|
playlistNext(deltaX < 0)
|
||||||
loadImage(true)
|
loadImage(true)
|
||||||
if (slideshowActive) {
|
if (slideshowActive) {
|
||||||
if (!slideshowSwipe) { // reset slideshow delay if user swipes
|
if (!slideshowSwipe) { //reset slideshow delay if user swipes
|
||||||
handler.removeCallbacks(slideshowNext)
|
handler.removeCallbacks(slideshowNext)
|
||||||
}
|
}
|
||||||
handler.postDelayed(slideshowNext, Constants.SLIDESHOW_DELAY)
|
handler.postDelayed(slideshowNext, Constants.SLIDESHOW_DELAY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun stopSlideshow(){
|
private fun stopSlideshow(){
|
||||||
slideshowActive = false
|
slideshowActive = false
|
||||||
|
@ -2,7 +2,6 @@ package sushi.hardcore.droidfs.file_viewers
|
|||||||
|
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.common.PlaybackException
|
import androidx.media3.common.PlaybackException
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
@ -12,7 +11,6 @@ import androidx.media3.exoplayer.ExoPlayer
|
|||||||
import androidx.media3.exoplayer.source.MediaSource
|
import androidx.media3.exoplayer.source.MediaSource
|
||||||
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
||||||
import androidx.media3.extractor.DefaultExtractorsFactory
|
import androidx.media3.extractor.DefaultExtractorsFactory
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import sushi.hardcore.droidfs.Constants
|
import sushi.hardcore.droidfs.Constants
|
||||||
import sushi.hardcore.droidfs.R
|
import sushi.hardcore.droidfs.R
|
||||||
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
|
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
|
||||||
@ -41,16 +39,12 @@ abstract class MediaPlayer: FileViewerActivity() {
|
|||||||
private fun initializePlayer(){
|
private fun initializePlayer(){
|
||||||
player = ExoPlayer.Builder(this).setSeekForwardIncrementMs(5000).build()
|
player = ExoPlayer.Builder(this).setSeekForwardIncrementMs(5000).build()
|
||||||
bindPlayer(player)
|
bindPlayer(player)
|
||||||
player.addMediaSource(createMediaSource(filePath))
|
|
||||||
lifecycleScope.launch {
|
|
||||||
createPlaylist()
|
createPlaylist()
|
||||||
playlist.forEachIndexed { index, e ->
|
for (e in mappedPlaylist) {
|
||||||
if (index != currentPlaylistIndex) {
|
player.addMediaSource(createMediaSource(e.fullPath))
|
||||||
player.addMediaSource(index, createMediaSource(e.fullPath))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
player.repeatMode = Player.REPEAT_MODE_ALL
|
player.repeatMode = Player.REPEAT_MODE_ALL
|
||||||
|
player.seekToDefaultPosition(currentPlaylistIndex)
|
||||||
player.playWhenReady = true
|
player.playWhenReady = true
|
||||||
player.addListener(object : Player.Listener{
|
player.addListener(object : Player.Listener{
|
||||||
override fun onVideoSizeChanged(videoSize: VideoSize) {
|
override fun onVideoSizeChanged(videoSize: VideoSize) {
|
||||||
@ -73,13 +67,11 @@ abstract class MediaPlayer: FileViewerActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
||||||
if (player.repeatMode != Player.REPEAT_MODE_ONE && currentPlaylistIndex != -1) {
|
if (player.repeatMode != Player.REPEAT_MODE_ONE) {
|
||||||
lifecycleScope.launch {
|
playlistNext(player.currentMediaItemIndex == (currentPlaylistIndex + 1) % mappedPlaylist.size)
|
||||||
playlistNext(player.currentMediaItemIndex == (currentPlaylistIndex + 1) % player.mediaItemCount)
|
|
||||||
refreshFileName()
|
refreshFileName()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
player.prepare()
|
player.prepare()
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ object AndroidUtils {
|
|||||||
/**
|
/**
|
||||||
* A [Manifest.permission.POST_NOTIFICATIONS] permission helper.
|
* A [Manifest.permission.POST_NOTIFICATIONS] permission helper.
|
||||||
*
|
*
|
||||||
* Must be initialized before [Activity.onCreate] finishes.
|
* Must be initialized before [Activity.onCreate].
|
||||||
*/
|
*/
|
||||||
class NotificationPermissionHelper<out A: AppCompatActivity>(val activity: A) {
|
class NotificationPermissionHelper<out A: AppCompatActivity>(val activity: A) {
|
||||||
private var listener: ((Boolean) -> Unit)? = null
|
private var listener: ((Boolean) -> Unit)? = null
|
||||||
|
@ -196,7 +196,6 @@ Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1list_1dir(JNIEnv
|
|||||||
jint sessionID, jstring jplain_dir) {
|
jint sessionID, jstring jplain_dir) {
|
||||||
const char* plain_dir = (*env)->GetStringUTFChars(env, jplain_dir, NULL);
|
const char* plain_dir = (*env)->GetStringUTFChars(env, jplain_dir, NULL);
|
||||||
const size_t plain_dir_len = strlen(plain_dir);
|
const size_t plain_dir_len = strlen(plain_dir);
|
||||||
const char append_slash = plain_dir[plain_dir_len-1] != '/';
|
|
||||||
GoString go_plain_dir = {plain_dir, plain_dir_len};
|
GoString go_plain_dir = {plain_dir, plain_dir_len};
|
||||||
|
|
||||||
struct gcf_list_dir_return elements = gcf_list_dir(sessionID, go_plain_dir);
|
struct gcf_list_dir_return elements = gcf_list_dir(sessionID, go_plain_dir);
|
||||||
@ -217,7 +216,7 @@ Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1list_1dir(JNIEnv
|
|||||||
|
|
||||||
char* fullPath = malloc(sizeof(char) * (plain_dir_len + nameLen + 2));
|
char* fullPath = malloc(sizeof(char) * (plain_dir_len + nameLen + 2));
|
||||||
strcpy(fullPath, plain_dir);
|
strcpy(fullPath, plain_dir);
|
||||||
if (append_slash) {
|
if (plain_dir[-2] != '/') {
|
||||||
strcat(fullPath, "/");
|
strcat(fullPath, "/");
|
||||||
}
|
}
|
||||||
strcat(fullPath, name);
|
strcat(fullPath, name);
|
||||||
|
@ -74,12 +74,11 @@
|
|||||||
<string name="usf_screenshot">אפשר צילומי מסך</string>
|
<string name="usf_screenshot">אפשר צילומי מסך</string>
|
||||||
<string name="usf_fingerprint">אפשר שימרת גיבוב של הסיסמא באמצעות טביעת אצבע</string>
|
<string name="usf_fingerprint">אפשר שימרת גיבוב של הסיסמא באמצעות טביעת אצבע</string>
|
||||||
<string name="usf_volume_management">הגדרת אמצעי אחסון</string>
|
<string name="usf_volume_management">הגדרת אמצעי אחסון</string>
|
||||||
<string name="usf_keep_open">השאר את האמצעי אחסון פתוח כשהאפליקציה רצה ברקע</string>
|
<string name="unsafe_features">פיצ'רים לא בטוחים</string>
|
||||||
<string name="unsafe_features">פיצרים לא בטוחים</string>
|
<string name="manage_unsafe_features">נהל פיצ'רים לא בטוחים</string>
|
||||||
<string name="manage_unsafe_features">נהל פיצרים לא בטוחים</string>
|
<string name="manage_unsafe_features_summary">אפשר/מנע פיצ'רים לא בטוחים</string>
|
||||||
<string name="manage_unsafe_features_summary">אפשר/מנע פיצרים לא בטוחים</string>
|
|
||||||
<string name="usf_home_warning_msg">DroidFS מנסה להיות מאובטח ככל האפשר,עם זאת אבטחה כרוכה לעיתים קרובת בחוסר נוחות. זה הסיבה ש DroidFS מציע פיצרים לא בטוחים שאתה יכול להפעיל /להשבית בהתאם לצרכים שלך .\n\n אזהרה: פיצרים אלה יכולים להיות לא בטוחים. אל תשתמש בהם אלא אם כן אתה יודע בידיוק מה אתה עושה. מומלץ מאוד לקרוא את הקובץ דוקמנטציה לפני שמפעילים אותם.</string>
|
<string name="usf_home_warning_msg">DroidFS מנסה להיות מאובטח ככל האפשר,עם זאת אבטחה כרוכה לעיתים קרובת בחוסר נוחות. זה הסיבה ש DroidFS מציע פיצרים לא בטוחים שאתה יכול להפעיל /להשבית בהתאם לצרכים שלך .\n\n אזהרה: פיצרים אלה יכולים להיות לא בטוחים. אל תשתמש בהם אלא אם כן אתה יודע בידיוק מה אתה עושה. מומלץ מאוד לקרוא את הקובץ דוקמנטציה לפני שמפעילים אותם.</string>
|
||||||
<string name="see_unsafe_features">הראה פיצרים לא בטוחים</string>
|
<string name="see_unsafe_features">הראה פיצ'רים לא בטוחים</string>
|
||||||
<string name="open_as">פתח כ</string>
|
<string name="open_as">פתח כ</string>
|
||||||
<string name="image">תמונה</string>
|
<string name="image">תמונה</string>
|
||||||
<string name="video">וידאו</string>
|
<string name="video">וידאו</string>
|
||||||
@ -141,7 +140,7 @@
|
|||||||
<string name="key_permanently_invalidated_exception">KeyPermanentlyInvalidatedException</string>
|
<string name="key_permanently_invalidated_exception">KeyPermanentlyInvalidatedException</string>
|
||||||
<string name="key_permanently_invalidated_exception_msg">נראה שהוספת טביעת אצבע חדשה. הגיבוב של סיסמאות שמורות הפך לבלתי שמיש.</string>
|
<string name="key_permanently_invalidated_exception_msg">נראה שהוספת טביעת אצבע חדשה. הגיבוב של סיסמאות שמורות הפך לבלתי שמיש.</string>
|
||||||
<string name="usf_read_doc">עליך לקרוא אותו בעיון לפני הפעלת כל אחת מהאפשרויות הללו.</string>
|
<string name="usf_read_doc">עליך לקרוא אותו בעיון לפני הפעלת כל אחת מהאפשרויות הללו.</string>
|
||||||
<string name="usf_doc">דוקמנטציה של פיצרים לא בטוחים</string>
|
<string name="usf_doc">דוקמנטציה של פיצ'רים לא בטוחים</string>
|
||||||
<string name="error_retrieving_filename">לא ניתן לאחזר את שם הקובץ עבור הקישור: %s</string>
|
<string name="error_retrieving_filename">לא ניתן לאחזר את שם הקובץ עבור הקישור: %s</string>
|
||||||
<string name="hidden_volume">אמצעי אחסון נסתר</string>
|
<string name="hidden_volume">אמצעי אחסון נסתר</string>
|
||||||
<string name="error_slash_in_name">שם האמצעי אחסון לא יכול להכיל סלאשים</string>
|
<string name="error_slash_in_name">שם האמצעי אחסון לא יכול להכיל סלאשים</string>
|
||||||
@ -197,7 +196,7 @@
|
|||||||
<string name="password_confirmation_label">חזור שנית על הסיסמא:</string>
|
<string name="password_confirmation_label">חזור שנית על הסיסמא:</string>
|
||||||
<string name="password_confirmation_hint">אישור סיסמא</string>
|
<string name="password_confirmation_hint">אישור סיסמא</string>
|
||||||
<string name="password_hash_saved">הגיבוב של הסיסמא נשמר</string>
|
<string name="password_hash_saved">הגיבוב של הסיסמא נשמר</string>
|
||||||
<string name="no_volumes_text">אין אמצעי אחסון שמורים, הוסף ע"י לחציה על הסימן +</string>
|
<string name="no_volumes_text">אין אמצעי אחסון שמורים, הוסף ע\"י לחציה על הסימן +</string>
|
||||||
<string name="fingerprint_error_msg">לא ניתן להשתמש באימות טביעת אצבע: %s.</string>
|
<string name="fingerprint_error_msg">לא ניתן להשתמש באימות טביעת אצבע: %s.</string>
|
||||||
<string name="keyguard_not_secure">מגן מקשים לא מאובטח</string>
|
<string name="keyguard_not_secure">מגן מקשים לא מאובטח</string>
|
||||||
<string name="no_hardware">לא נמצאה חומרה מתאימה</string>
|
<string name="no_hardware">לא נמצאה חומרה מתאימה</string>
|
||||||
@ -212,7 +211,7 @@
|
|||||||
<string name="new_password_label">הזן את הסיסמא החדשה לאמצעי אחסון:</string>
|
<string name="new_password_label">הזן את הסיסמא החדשה לאמצעי אחסון:</string>
|
||||||
<string name="new_password_hint">סיסמא חדשה</string>
|
<string name="new_password_hint">סיסמא חדשה</string>
|
||||||
<string name="new_password_confirmation_label">חזור שנית על הסיסמא החדשה:</string>
|
<string name="new_password_confirmation_label">חזור שנית על הסיסמא החדשה:</string>
|
||||||
<string name="error_marshmallow_required">הפיצר הזה זמין רק למשתמשי אנדרואיד 6 (מרשמלו) ומעלה</string>
|
<string name="error_marshmallow_required">הפיצ'ר הזה זמין רק למשתמשי אנדרואיד 6 (מרשמלו) ומעלה</string>
|
||||||
<string name="copy_hidden_volume">העתק לאחסון משותף</string>
|
<string name="copy_hidden_volume">העתק לאחסון משותף</string>
|
||||||
<string name="copy_external_volume">צור עותק נסתר</string>
|
<string name="copy_external_volume">צור עותק נסתר</string>
|
||||||
<string name="copy_volume_notification">מעתיק אמצעי אחסון…</string>
|
<string name="copy_volume_notification">מעתיק אמצעי אחסון…</string>
|
||||||
@ -231,7 +230,7 @@
|
|||||||
<string name="multiple_folders">%d תיקיות</string>
|
<string name="multiple_folders">%d תיקיות</string>
|
||||||
<string name="default_open">פתח אמצעי אחסון זה בעת הפעלת היישום</string>
|
<string name="default_open">פתח אמצעי אחסון זה בעת הפעלת היישום</string>
|
||||||
<string name="remove_default_open">אל תפתח כברירת מחדל</string>
|
<string name="remove_default_open">אל תפתח כברירת מחדל</string>
|
||||||
<string name="elements_selected">%d/%d נבחרו</string>
|
<string name="elements_selected" formatted="false">%d/%d נבחרו</string>
|
||||||
<string name="pin_passwords_title">פריסת מקלדת מספרים</string>
|
<string name="pin_passwords_title">פריסת מקלדת מספרים</string>
|
||||||
<string name="pin_passwords_summary">שימוש בפריסת מקלדת מספרים בעת הזנת סיסמאות אמצעי אחסון</string>
|
<string name="pin_passwords_summary">שימוש בפריסת מקלדת מספרים בעת הזנת סיסמאות אמצעי אחסון</string>
|
||||||
<string name="volume_type_label">סוג אמצעי אחסון:</string>
|
<string name="volume_type_label">סוג אמצעי אחסון:</string>
|
||||||
@ -279,4 +278,18 @@
|
|||||||
<string name="debug">דיבאג</string>
|
<string name="debug">דיבאג</string>
|
||||||
<string name="logcat_title">DroidFS Logcat</string>
|
<string name="logcat_title">DroidFS Logcat</string>
|
||||||
<string name="logcat_saved">Logcat נשמר</string>
|
<string name="logcat_saved">Logcat נשמר</string>
|
||||||
|
<string name="later">אחר כך</string>
|
||||||
|
<string name="notification_denied_msg">הרשאת ההתראות נדחתה. פעולות קובץ ברקע לא יהיו נראות. אתה יכול לשנות זאת בהגדרות ההרשאות של האפליקציה.</string>
|
||||||
|
<string name="keep_alive_notification_title">שומר על האפליקציה שתרוץ ברקע</string>
|
||||||
|
<string name="keep_alive_notification_text">אמצעי אחסון אחד או יותר נשמרים פתוחים.</string>
|
||||||
|
<string name="close_all">סגור הכל</string>
|
||||||
|
<string name="usf_background">בטל נעילה אוטומטית לאמצעי אחסון</string>
|
||||||
|
<string name="usf_background_summary">אל תנעל את האמצעי אחסון כשהאפליקציה רצה ברקע</string>
|
||||||
|
<string name="usf_keep_open">השאר את האמצעי אחסון פתוח כשהאפליקציה רצה ברקע</string>
|
||||||
|
<string name="usf_keep_open_summary">השאר את האפליקציה רצה תמיד ברקע כדי לשמור על אמצעי אחסון פתוחים</string>
|
||||||
|
<string name="gocryptfs_details">מהיר, אבל לא מסתיר את גדול הקבצים ומבנה התיקיות.</string>
|
||||||
|
<string name="cryfs_details">איטי יותר, אבל מגן על מטא נתונים (גודל קבצים ומבנה תיקיות)
|
||||||
|
ומונע מתקפה של החלפת קבצים.</string>
|
||||||
|
<string name="or">או</string>
|
||||||
|
<string name="enter_volume_path">הכנס מתיב תיקייה</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user