diff --git a/CHANGELOG.md b/CHANGELOG.md index c277055d4..00150c15f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,87 @@ Changelog ========== +Version 6.8.1 *(2019-06-27)* +---------------------------- + + * Improved Search on the main screen, allow using it for searching all files, not folders + * Added Print functionality at fullscreen images + * Fixed a glitch at PNGs getting deleted after rotating + * Other stability, translation and performance improvements + +Version 6.8.0 *(2019-06-21)* +---------------------------- + + * Allow grouping files by date_taken or last_modified either daily, or monthly + * Allow selecting fade animation or no animation at all at slideshow transitions + * Improved the performance at loading fullscreen videos + * Use last_modified value at batch file renaming, if date_taken isn't available + * Some other stability and translation improvements + +Version 6.7.9 *(2019-06-12)* +---------------------------- + + * Fixed a crash at zooming + +Version 6.7.8 *(2019-06-11)* +---------------------------- + + * Improved the UX at zooming and panning at the fullscreen view + * Fixed unchecking Favorite items in some cases + * Show the available aspect ratios at the editor by default + * Couple stability, performance and translation improvements + +Version 6.7.7 *(2019-05-28)* +---------------------------- + + * Fixed some file deleting related glitches + * Improved batch renaming, use the old file extension in case a new one is missing + +Version 6.7.6 *(2019-05-26)* +---------------------------- + + * Improved batch renaming, allow using date time patterns in it + * Fixed empty folder deleting after deleting its content + * Improved new file cache updating in the background + * Improved the placeholder text in case no files are found + * Keep last_modified field at deleting and restoring files from the bin + * Increase the max image duration at slideshows + * Highlight the warning at deleting a folder + * Other stability, translation and performance improvements + +Version 6.7.5 *(2019-05-15)* +---------------------------- + + * Hotfixing a glitch with opening third party intents + +Version 6.7.4 *(2019-05-15)* +---------------------------- + + * Speeded up video deleting from fullscreen view + * Hotfixed some crashes + +Version 6.7.3 *(2019-05-14)* +---------------------------- + + * Fixed folder sorting if used together with subfolder grouping + * Fixed some copy/move related progressbar issues + * Added many performance and stability improvements + +Version 6.7.2 *(2019-05-09)* +---------------------------- + + * Allow creating file or folder shortcuts only from Android 8+ + +Version 6.7.1 *(2019-05-08)* +---------------------------- + + * Allow creating file or folder shortcuts on home screen on Android 7+ + * Allow creating new folders on the file thumbnails screen too + * Added a checkbox at sorting by name/path to sort numbers by their actual numeric value + * Improve grouping direct subfolders, do not ignore parent folders without media files + * Show the Open Camera button at the menu on the main screen, instead of the Sort by button + * Other translation and stability improvements + Version 6.7.0 *(2019-05-02)* ---------------------------- diff --git a/app/build.gradle b/app/build.gradle index d97d7bd30..f03764864 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { applicationId "com.simplemobiletools.gallery.pro" minSdkVersion 21 targetSdkVersion 28 - versionCode 244 - versionName "6.7.0" + versionCode 255 + versionName "6.8.1" multiDexEnabled true setProperty("archivesBaseName", "gallery") } @@ -61,24 +61,24 @@ android { } dependencies { - implementation 'com.simplemobiletools:commons:5.12.12' + implementation 'com.simplemobiletools:commons:5.14.2' implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0' implementation 'androidx.multidex:multidex:2.0.1' implementation 'it.sephiroth.android.exif:library:1.0.1' - implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.16' - implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha5' - implementation 'com.google.android.exoplayer:exoplayer-core:2.9.6' + implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.17' + implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2' + implementation 'com.google.android.exoplayer:exoplayer-core:2.10.2' implementation 'com.google.vr:sdk-panowidget:1.180.0' implementation 'com.google.vr:sdk-videowidget:1.180.0' implementation 'org.apache.sanselan:sanselan:0.97-incubator' implementation 'info.androidhive:imagefilters:1.0.7' implementation 'com.squareup.picasso:picasso:2.71828' implementation 'com.caverock:androidsvg-aar:1.3' - implementation 'com.github.tibbi:gestureviews:1506ec6156' - implementation 'com.github.tibbi:subsampling-scale-image-view:1df78cdfff' + implementation 'com.github.tibbi:gestureviews:4444214285' + implementation 'com.github.tibbi:subsampling-scale-image-view:55eb1ddd5b' kapt 'com.github.bumptech.glide:compiler:4.9.0' // keep it here too, not just in Commons, else loading SVGs wont work - kapt 'androidx.room:room-compiler:2.0.0' - implementation 'androidx.room:room-runtime:2.0.0' - annotationProcessor 'androidx.room:room-compiler:2.0.0' + kapt 'androidx.room:room-compiler:2.1.0' + implementation 'androidx.room:room-runtime:2.1.0' + annotationProcessor 'androidx.room:room-compiler:2.1.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index aa2a48308..25f4250ff 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -36,14 +36,6 @@ android:name=".activities.MainActivity" android:resizeableActivity="true"> - - - - - - @@ -81,6 +73,21 @@ + + + + + + + + + ? = null private var currPrimaryAction = PRIMARY_ACTION_NONE - private var currCropRotateAction = CROP_ROTATE_NONE + private var currCropRotateAction = CROP_ROTATE_ASPECT_RATIO private var currAspectRatio = ASPECT_RATIO_FREE private var isCropIntent = false private var isEditingWithThirdParty = false @@ -189,6 +186,8 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener lastOtherAspectRatio = Pair(config.lastEditorCropOtherAspectRatioX, config.lastEditorCropOtherAspectRatioY) } updateAspectRatio(config.lastEditorCropAspectRatio) + crop_image_view.guidelines = CropImageView.Guidelines.ON + bottom_aspect_ratios.beVisible() } private fun loadDefaultImageView() { @@ -257,9 +256,9 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener if (!wasDrawCanvasPositioned) { wasDrawCanvasPositioned = true editor_draw_canvas.onGlobalLayout { - Thread { + ensureBackgroundThread { fillCanvasBackground() - }.start() + } } } } @@ -334,7 +333,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener bottom_actions_filter_list.adapter = null bottom_actions_filter_list.beGone() - Thread { + ensureBackgroundThread { try { val originalBitmap = Glide.with(applicationContext).asBitmap().load(uri).submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).get() currentFilter.filter.processFilter(originalBitmap) @@ -342,23 +341,23 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener } catch (e: OutOfMemoryError) { toast(R.string.out_of_memory_error) } - }.start() + } } } } private fun shareImage() { - Thread { + ensureBackgroundThread { when { default_image_view.isVisible() -> { val currentFilter = getFiltersAdapter()?.getCurrentFilter() if (currentFilter == null) { toast(R.string.unknown_error_occurred) - return@Thread + return@ensureBackgroundThread } val originalBitmap = Glide.with(applicationContext).asBitmap().load(uri).submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).get() - currentFilter!!.filter.processFilter(originalBitmap) + currentFilter.filter.processFilter(originalBitmap) shareBitmap(originalBitmap) } crop_image_view.isVisible() -> { @@ -369,12 +368,12 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener } editor_draw_canvas.isVisible() -> shareBitmap(editor_draw_canvas.getBitmap()) } - }.start() + } } private fun getTempImagePath(bitmap: Bitmap, callback: (path: String?) -> Unit) { val bytes = ByteArrayOutputStream() - bitmap.compress(Bitmap.CompressFormat.PNG, 0, bytes) + bitmap.compress(CompressFormat.PNG, 0, bytes) val folder = File(cacheDir, TEMP_FOLDER_NAME) if (!folder.exists()) { @@ -579,20 +578,27 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener bottom_editor_draw_actions.beVisibleIf(currPrimaryAction == PRIMARY_ACTION_DRAW) if (currPrimaryAction == PRIMARY_ACTION_FILTER && bottom_actions_filter_list.adapter == null) { - Thread { + ensureBackgroundThread { val thumbnailSize = resources.getDimension(R.dimen.bottom_filters_thumbnail_size).toInt() - val bitmap = Glide.with(this) - .asBitmap() - .load(uri).listener(object : RequestListener { - override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { - showErrorToast(e.toString()) - return false - } - override fun onResourceReady(resource: Bitmap?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean) = false - }) - .submit(thumbnailSize, thumbnailSize) - .get() + val bitmap = try { + Glide.with(this) + .asBitmap() + .load(uri).listener(object : RequestListener { + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { + showErrorToast(e.toString()) + return false + } + + override fun onResourceReady(resource: Bitmap?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean) = false + }) + .submit(thumbnailSize, thumbnailSize) + .get() + } catch (e: GlideException) { + showErrorToast(e) + finish() + return@ensureBackgroundThread + } runOnUiThread { val filterThumbnailsManager = FilterThumbnailsManager() @@ -621,14 +627,14 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener bottom_actions_filter_list.adapter = adapter adapter.notifyDataSetChanged() } - }.start() + } } if (currPrimaryAction != PRIMARY_ACTION_CROP_ROTATE) { bottom_aspect_ratios.beGone() currCropRotateAction = CROP_ROTATE_NONE - updateCropRotateActionButtons() } + updateCropRotateActionButtons() } private fun applyFilter(filterItem: FilterItem) { @@ -802,7 +808,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener private fun saveBitmapToFile(bitmap: Bitmap, path: String, showSavingToast: Boolean) { try { - Thread { + ensureBackgroundThread { val file = File(path) val fileDirItem = FileDirItem(path, path.getFilenameFromPath()) getFileOutputStream(fileDirItem, true) { @@ -812,7 +818,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener toast(R.string.image_editing_failed) } } - }.start() + } } catch (e: Exception) { showErrorToast(e) } catch (e: OutOfMemoryError) { @@ -852,7 +858,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener } private fun scanFinalPath(path: String) { - scanPathRecursively(path) { + rescanPaths(arrayListOf(path)) { setResult(Activity.RESULT_OK, intent) toast(R.string.file_saved) finish() diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/HiddenFoldersActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/HiddenFoldersActivity.kt index 98d5eb9d9..a7a5002ba 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/HiddenFoldersActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/HiddenFoldersActivity.kt @@ -5,6 +5,7 @@ import android.view.Menu import android.view.MenuItem import com.simplemobiletools.commons.dialogs.FilePickerDialog import com.simplemobiletools.commons.extensions.beVisibleIf +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.adapters.ManageHiddenFoldersAdapter @@ -55,11 +56,11 @@ class HiddenFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener { private fun addFolder() { FilePickerDialog(this, config.lastFilepickerPath, false, config.shouldShowHidden, false, true) { config.lastFilepickerPath = it - Thread { + ensureBackgroundThread { addNoMedia(it) { updateFolders() } - }.start() + } } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/IncludedFoldersActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/IncludedFoldersActivity.kt index b6be4add2..f4e0258c3 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/IncludedFoldersActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/IncludedFoldersActivity.kt @@ -3,9 +3,7 @@ package com.simplemobiletools.gallery.pro.activities import android.os.Bundle import android.view.Menu import android.view.MenuItem -import com.simplemobiletools.commons.dialogs.FilePickerDialog import com.simplemobiletools.commons.extensions.beVisibleIf -import com.simplemobiletools.commons.extensions.scanPathRecursively import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.adapters.ManageFoldersAdapter @@ -50,13 +48,8 @@ class IncludedFoldersActivity : SimpleActivity(), RefreshRecyclerViewListener { } private fun addFolder() { - FilePickerDialog(this, config.lastFilepickerPath, false, config.shouldShowHidden, false, true) { - config.lastFilepickerPath = it - config.addIncludedFolder(it) + showAddIncludedFolderDialog { updateFolders() - Thread { - scanPathRecursively(it) - }.start() } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MainActivity.kt index ed1ddee6b..4b25b4bb0 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MainActivity.kt @@ -1,9 +1,7 @@ package com.simplemobiletools.gallery.pro.activities import android.app.Activity -import android.app.SearchManager import android.content.ClipData -import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle @@ -14,8 +12,6 @@ import android.view.MenuItem import android.view.ViewGroup import android.widget.FrameLayout import android.widget.Toast -import androidx.appcompat.widget.SearchView -import androidx.core.view.MenuItemCompat import androidx.recyclerview.widget.RecyclerView import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.dialogs.CreateNewFolderDialog @@ -39,7 +35,6 @@ import com.simplemobiletools.gallery.pro.interfaces.DirectoryDao import com.simplemobiletools.gallery.pro.interfaces.DirectoryOperationsListener import com.simplemobiletools.gallery.pro.interfaces.MediumDao import com.simplemobiletools.gallery.pro.jobs.NewPhotoFetcher -import com.simplemobiletools.gallery.pro.models.AlbumCover import com.simplemobiletools.gallery.pro.models.Directory import com.simplemobiletools.gallery.pro.models.Medium import kotlinx.android.synthetic.main.activity_main.* @@ -66,7 +61,6 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { private var mIsPasswordProtectionPending = false private var mWasProtectionHandled = false private var mShouldStopFetching = false - private var mIsSearchOpen = false private var mLatestMediaId = 0L private var mLatestMediaDateId = 0L private var mCurrentPathPrefix = "" // used at "Group direct subfolders" for navigation @@ -74,7 +68,6 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { private var mLastMediaHandler = Handler() private var mTempShowHiddenHandler = Handler() private var mZoomListener: MyRecyclerView.MyZoomListener? = null - private var mSearchMenuItem: MenuItem? = null private var mDirs = ArrayList() private var mStoredAnimateGifs = true @@ -118,10 +111,6 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { storeStateVariables() checkWhatsNewDialog() - directories_empty_text.setOnClickListener { - showFilterMediaDialog() - } - mIsPasswordProtectionPending = config.isAppPasswordProtectionOn setupLatestMediaId() @@ -139,7 +128,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { if (!config.wasRecycleBinPinned) { config.addPinnedFolders(hashSetOf(RECYCLE_BIN)) config.wasRecycleBinPinned = true - config.saveFolderGrouping(SHOW_ALL, GROUP_BY_DATE_TAKEN or GROUP_DESCENDING) + config.saveFolderGrouping(SHOW_ALL, GROUP_BY_DATE_TAKEN_DAILY or GROUP_DESCENDING) } if (!config.wasSVGShowingHandled) { @@ -149,6 +138,11 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { } } + if (!config.wasSortingByNumericValueAdded) { + config.wasSortingByNumericValueAdded = true + config.sorting = config.sorting or SORT_USE_NUMERIC_VALUE + } + updateWidgets() registerFileUpdateListener() } @@ -224,8 +218,6 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { override fun onStop() { super.onStop() - mSearchMenuItem?.collapseActionView() - if (config.temporarilyShowHidden || config.tempSkipDeleteConfirmation) { mTempShowHiddenHandler.postDelayed({ config.temporarilyShowHidden = false @@ -276,7 +268,6 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { findItem(R.id.reduce_column_count).isVisible = config.viewTypeFolders == VIEW_TYPE_GRID && config.dirColumnCnt > 1 findItem(R.id.hide_the_recycle_bin).isVisible = useBin && config.showRecycleBinAtFolders findItem(R.id.show_the_recycle_bin).isVisible = useBin && !config.showRecycleBinAtFolders - setupSearch(this) } } @@ -288,6 +279,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { + R.id.search -> launchSearchActivity() R.id.sort -> showSortingDialog() R.id.filter -> showFilterMediaDialog() R.id.open_camera -> launchCamera() @@ -331,43 +323,6 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { } } - private fun setupSearch(menu: Menu) { - val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager - mSearchMenuItem = menu.findItem(R.id.search) - (mSearchMenuItem?.actionView as? SearchView)?.apply { - setSearchableInfo(searchManager.getSearchableInfo(componentName)) - isSubmitButtonEnabled = false - setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(query: String) = false - - override fun onQueryTextChange(newText: String): Boolean { - if (mIsSearchOpen) { - setupAdapter(mDirs, newText) - } - return true - } - }) - } - - MenuItemCompat.setOnActionExpandListener(mSearchMenuItem, object : MenuItemCompat.OnActionExpandListener { - override fun onMenuItemActionExpand(item: MenuItem?): Boolean { - mIsSearchOpen = true - directories_refresh_layout.isEnabled = false - return true - } - - // this triggers on device rotation too, avoid doing anything - override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { - if (mIsSearchOpen) { - mIsSearchOpen = false - directories_refresh_layout.isEnabled = config.enablePullToRefresh - setupAdapter(mDirs, "") - } - return true - } - }) - } - private fun startNewPhotoFetcher() { if (isNougatPlus()) { val photoFetcher = NewPhotoFetcher() @@ -383,7 +338,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { if (newFolder.exists() && newFolder.isDirectory) { if (newFolder.list()?.isEmpty() == true) { toast(String.format(getString(R.string.deleting_folder), config.tempFolderPath), Toast.LENGTH_LONG) - tryDeleteFileDirItem(newFolder.toFileDirItem(applicationContext), true, true) + tryDeleteFileDirItem(newFolder.toFileDirItem(), true, true) } } config.tempFolderPath = "" @@ -391,7 +346,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { } private fun checkOTGPath() { - Thread { + ensureBackgroundThread { if (!config.wasOTGHandled && hasPermission(PERMISSION_WRITE_STORAGE) && hasOTGConnected() && config.OTGPath.isEmpty()) { getStorageDirectories().firstOrNull { it.trimEnd('/') != internalStoragePath && it.trimEnd('/') != sdCardPath }?.apply { config.wasOTGHandled = true @@ -409,7 +364,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { } } } - }.start() + } } private fun checkDefaultSpamFolders() { @@ -467,15 +422,21 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { } } + private fun launchSearchActivity() { + Intent(this, SearchActivity::class.java).apply { + startActivity(this) + } + } + private fun showSortingDialog() { ChangeSortingDialog(this, true, false) { directories_grid.adapter = null if (config.directorySorting and SORT_BY_DATE_MODIFIED > 0 || config.directorySorting and SORT_BY_DATE_TAKEN > 0) { getDirectories() } else { - Thread { + ensureBackgroundThread { gotDirectories(getCurrentlyDisplayedDirs()) - }.start() + } } } } @@ -554,7 +515,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { (it.isGif() && filter and TYPE_GIFS != 0) || (it.isRawFast() && filter and TYPE_RAWS != 0) || (it.isSvg() && filter and TYPE_SVGS != 0)) - }?.mapTo(itemsToDelete) { it.toFileDirItem(this) } + }?.mapTo(itemsToDelete) { it.toFileDirItem() } } if (config.useRecycleBin) { @@ -579,11 +540,11 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { refreshItems() } - Thread { + ensureBackgroundThread { folders.filter { !it.exists() }.forEach { mDirectoryDao.deleteDirPath(it.absolutePath) } - }.start() + } } } @@ -668,22 +629,22 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { private fun toggleRecycleBin(show: Boolean) { config.showRecycleBinAtFolders = show invalidateOptionsMenu() - Thread { + ensureBackgroundThread { var dirs = getCurrentlyDisplayedDirs() if (!show) { dirs = dirs.filter { it.path != RECYCLE_BIN } as ArrayList } gotDirectories(dirs) - }.start() + } } private fun createNewFolder() { FilePickerDialog(this, internalStoragePath, false, config.shouldShowHidden, false, true) { CreateNewFolderDialog(this, it) { config.tempFolderPath = it - Thread { + ensureBackgroundThread { gotDirectories(addTempFolderIfNeeded(getCurrentlyDisplayedDirs())) - }.start() + } } } } @@ -999,26 +960,27 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { private fun checkPlaceholderVisibility(dirs: ArrayList) { directories_empty_text_label.beVisibleIf(dirs.isEmpty() && mLoadedInitialPhotos) directories_empty_text.beVisibleIf(dirs.isEmpty() && mLoadedInitialPhotos) - directories_grid.beVisibleIf(directories_empty_text_label.isGone()) - } - private fun createDirectoryFromMedia(path: String, curMedia: ArrayList, albumCovers: ArrayList, hiddenString: String, - includedFolders: MutableSet, isSortingAscending: Boolean, getProperFileSize: Boolean): Directory { - var thumbnail = curMedia.firstOrNull { File(it.path).exists() }?.path ?: "" - albumCovers.forEach { - if (it.path == path && File(it.tmb).exists()) { - thumbnail = it.tmb + if (dirs.isEmpty() && config.filterMedia == TYPE_DEFAULT_FILTER) { + directories_empty_text_label.text = getString(R.string.no_media_add_included) + directories_empty_text.text = getString(R.string.add_folder) + + directories_empty_text.setOnClickListener { + showAddIncludedFolderDialog { + refreshItems() + } + } + } else { + directories_empty_text_label.text = getString(R.string.no_media_with_filters) + directories_empty_text.text = getString(R.string.change_filters_underlined) + + directories_empty_text.setOnClickListener { + showFilterMediaDialog() } } - val firstItem = curMedia.first() - val lastItem = curMedia.last() - val dirName = checkAppendingHidden(path, hiddenString, includedFolders) - val lastModified = if (isSortingAscending) Math.min(firstItem.modified, lastItem.modified) else Math.max(firstItem.modified, lastItem.modified) - val dateTaken = if (isSortingAscending) Math.min(firstItem.taken, lastItem.taken) else Math.max(firstItem.taken, lastItem.taken) - val size = if (getProperFileSize) curMedia.sumByLong { it.size } else 0L - val mediaTypes = curMedia.getDirMediaTypes() - return Directory(null, path, thumbnail, dirName, curMedia.size, lastModified, dateTaken, size, getPathLocation(path), mediaTypes) + directories_empty_text.underlineText() + directories_grid.beVisibleIf(directories_empty_text_label.isGone()) } private fun setupAdapter(dirs: ArrayList, textToSearch: String = "") { @@ -1136,12 +1098,12 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { ?: "" private fun setupLatestMediaId() { - Thread { + ensureBackgroundThread { if (hasPermission(PERMISSION_READ_STORAGE)) { mLatestMediaId = getLatestMediaId() mLatestMediaDateId = getLatestMediaByDateId() } - }.start() + } } private fun checkLastMediaChanged() { @@ -1150,7 +1112,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { } mLastMediaHandler.postDelayed({ - Thread { + ensureBackgroundThread { val mediaId = getLatestMediaId() val mediaDateId = getLatestMediaByDateId() if (mLatestMediaId != mediaId || mLatestMediaDateId != mediaDateId) { @@ -1163,7 +1125,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { mLastMediaHandler.removeCallbacksAndMessages(null) checkLastMediaChanged() } - }.start() + } }, LAST_MEDIA_CHECK_PERIOD) } @@ -1171,12 +1133,12 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { if (config.useRecycleBin && config.lastBinCheck < System.currentTimeMillis() - DAY_SECONDS * 1000) { config.lastBinCheck = System.currentTimeMillis() Handler().postDelayed({ - Thread { + ensureBackgroundThread { try { mMediumDao.deleteOldRecycleBinItems(System.currentTimeMillis() - MONTH_MILLISECONDS) } catch (e: Exception) { } - }.start() + } }, 3000L) } } @@ -1185,7 +1147,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { // /storage/emulated/0/Android/data/com.facebook.orca/files/stickers/175139712676531/209575122566323 // /storage/emulated/0/Android/data/com.facebook.orca/files/stickers/497837993632037/499671223448714 private fun excludeSpamFolders() { - Thread { + ensureBackgroundThread { try { val internalPath = internalStoragePath val checkedPaths = ArrayList() @@ -1222,7 +1184,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { } } catch (e: Exception) { } - }.start() + } } override fun refreshItems() { @@ -1230,16 +1192,16 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { } override fun recheckPinnedFolders() { - Thread { + ensureBackgroundThread { gotDirectories(movePinnedDirectoriesToFront(getCurrentlyDisplayedDirs())) - }.start() + } } override fun updateDirectories(directories: ArrayList) { - Thread { + ensureBackgroundThread { storeDirectoryItems(directories, mDirectoryDao) removeInvalidDBDirectories() - }.start() + } } private fun checkWhatsNewDialog() { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MediaActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MediaActivity.kt index dff45ff8f..f79e0a1f5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MediaActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/MediaActivity.kt @@ -22,10 +22,12 @@ import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.SimpleTarget import com.bumptech.glide.request.transition.Transition import com.simplemobiletools.commons.dialogs.ConfirmationDialog +import com.simplemobiletools.commons.dialogs.CreateNewFolderDialog import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE import com.simplemobiletools.commons.helpers.REQUEST_EDIT_IMAGE import com.simplemobiletools.commons.helpers.SORT_BY_RANDOM +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.models.FileDirItem import com.simplemobiletools.commons.views.MyGridLayoutManager import com.simplemobiletools.commons.views.MyRecyclerView @@ -220,6 +222,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { findItem(R.id.folder_view).isVisible = mShowAll findItem(R.id.open_camera).isVisible = mShowAll findItem(R.id.about).isVisible = mShowAll + findItem(R.id.create_new_folder).isVisible = !mShowAll && mPath != RECYCLE_BIN && mPath != FAVORITES findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden findItem(R.id.stop_showing_hidden).isVisible = config.temporarilyShowHidden @@ -249,6 +252,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { R.id.hide_folder -> tryHideFolder() R.id.unhide_folder -> unhideFolder() R.id.exclude_folder -> tryExcludeFolder() + R.id.create_new_folder -> createNewFolder() R.id.temporarily_show_hidden -> tryToggleTemporarilyShowHidden() R.id.stop_showing_hidden -> tryToggleTemporarilyShowHidden() R.id.increase_column_count -> increaseColumnCount() @@ -324,18 +328,25 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { } private fun searchQueryChanged(text: String) { - Thread { + ensureBackgroundThread { try { val filtered = mMedia.filter { it is Medium && it.name.contains(text, true) } as ArrayList filtered.sortBy { it is Medium && !it.name.startsWith(text, true) } val grouped = MediaFetcher(applicationContext).groupMedia(filtered as ArrayList, mPath) runOnUiThread { + if (grouped.isEmpty()) { + media_empty_text_label.text = getString(R.string.no_items_found) + media_empty_text_label.beVisible() + } else { + media_empty_text_label.beGone() + } + getMediaAdapter()?.updateMedia(grouped) measureRecyclerViewContent(grouped) } } catch (ignored: Exception) { } - }.start() + } } private fun tryLoadGallery() { @@ -425,7 +436,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { mLastMediaHandler.removeCallbacksAndMessages(null) mLastMediaHandler.postDelayed({ - Thread { + ensureBackgroundThread { val mediaId = getLatestMediaId() val mediaDateId = getLatestMediaByDateId() if (mLatestMediaId != mediaId || mLatestMediaDateId != mediaDateId) { @@ -437,7 +448,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { } else { checkLastMediaChanged() } - }.start() + } }, LAST_MEDIA_CHECK_PERIOD) } @@ -477,9 +488,9 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { private fun restoreAllFiles() { val paths = mMedia.filter { it is Medium }.map { (it as Medium).path } as ArrayList restoreRecycleBinPaths(paths, mMediumDao) { - Thread { + ensureBackgroundThread { mDirectoryDao.deleteDirPath(RECYCLE_BIN) - }.start() + } finish() } } @@ -583,7 +594,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { private fun startAsyncTask() { mCurrAsyncTask?.stopFetching() mCurrAsyncTask = GetMediaAsynctask(applicationContext, mPath, mIsGetImageIntent, mIsGetVideoIntent, mShowAll) { - Thread { + ensureBackgroundThread { val oldMedia = mMedia.clone() as ArrayList val newMedia = it gotMedia(newMedia, false) @@ -593,7 +604,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { } } catch (e: Exception) { } - }.start() + } } mCurrAsyncTask!!.execute() @@ -607,9 +618,9 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { } if (mPath == FAVORITES) { - Thread { + ensureBackgroundThread { mDirectoryDao.deleteDirPath(FAVORITES) - }.start() + } } finish() @@ -620,9 +631,15 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { } private fun deleteDBDirectory() { - Thread { + ensureBackgroundThread { mDirectoryDao.deleteDirPath(mPath) - }.start() + } + } + + private fun createNewFolder() { + CreateNewFolderDialog(this, mPath) { + config.tempFolderPath = it + } } private fun tryToggleTemporarilyShowHidden() { @@ -837,6 +854,10 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { media_refresh_layout.isRefreshing = false media_empty_text_label.beVisibleIf(media.isEmpty() && !isFromCache) media_empty_text.beVisibleIf(media.isEmpty() && !isFromCache) + + if (media_empty_text_label.isVisible()) { + media_empty_text_label.text = getString(R.string.no_media_with_filters) + } media_grid.beVisibleIf(media_empty_text_label.isGone()) val viewType = config.getFolderViewType(if (mShowAll) SHOW_ALL else mPath) @@ -890,14 +911,14 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { mMedia.removeAll { filtered.map { it.path }.contains((it as? Medium)?.path) } - Thread { + ensureBackgroundThread { val useRecycleBin = config.useRecycleBin filtered.forEach { if (it.path.startsWith(recycleBinPath) || !useRecycleBin) { deleteDBPath(mMediumDao, it.path) } } - }.start() + } if (mMedia.isEmpty()) { deleteDirectoryIfEmpty() diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaPhotoActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaPhotoActivity.kt index fa8dcfb54..c69cd5271 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaPhotoActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PanoramaPhotoActivity.kt @@ -15,6 +15,7 @@ import com.simplemobiletools.commons.extensions.onGlobalLayout import com.simplemobiletools.commons.extensions.showErrorToast import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.extensions.* import com.simplemobiletools.gallery.pro.helpers.PATH @@ -94,7 +95,7 @@ open class PanoramaPhotoActivity : SimpleActivity() { try { val options = VrPanoramaView.Options() options.inputType = VrPanoramaView.Options.TYPE_MONO - Thread { + ensureBackgroundThread { val bitmap = getBitmapToLoad(path) runOnUiThread { panorama_view.apply { @@ -120,7 +121,7 @@ open class PanoramaPhotoActivity : SimpleActivity() { }) } } - }.start() + } } catch (e: Exception) { showErrorToast(e) } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PhotoVideoActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PhotoVideoActivity.kt index b8632b877..c27186cd4 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PhotoVideoActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/PhotoVideoActivity.kt @@ -97,9 +97,11 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList val realPath = intent.extras!!.getString(REAL_FILE_PATH) if (realPath != null && File(realPath).exists()) { if (realPath.getFilenameFromPath().contains('.') || filename.contains('.')) { - sendViewPagerIntent(realPath) - finish() - return + if (isFileTypeVisible(realPath)) { + sendViewPagerIntent(realPath) + finish() + return + } } else { filename = realPath.getFilenameFromPath() } @@ -108,7 +110,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList if (mUri!!.scheme == "file") { if (filename.contains('.')) { - scanPathRecursively(mUri!!.path) + rescanPaths(arrayListOf(mUri!!.path)) sendViewPagerIntent(mUri!!.path) finish() return @@ -116,10 +118,12 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList } else { val path = applicationContext.getRealPathFromURI(mUri!!) ?: "" if (path != mUri.toString() && path.isNotEmpty() && mUri!!.authority != "mms" && filename.contains('.') && File(path).exists()) { - scanPathRecursively(mUri!!.path) - sendViewPagerIntent(path) - finish() - return + if (isFileTypeVisible(path)) { + rescanPaths(arrayListOf(mUri!!.path)) + sendViewPagerIntent(path) + finish() + return + } } } @@ -253,6 +257,15 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList PropertiesDialog(this, mUri!!.path) } + private fun isFileTypeVisible(path: String): Boolean { + val filter = config.filterMedia + return !(path.isImageFast() && filter and TYPE_IMAGES == 0 || + path.isVideoFast() && filter and TYPE_VIDEOS == 0 || + path.isGif() && filter and TYPE_GIFS == 0 || + path.isRawFast() && filter and TYPE_RAWS == 0 || + path.isSvg() && filter and TYPE_SVGS == 0) + } + private fun initBottomActions() { initBottomActionsLayout() initBottomActionButtons() diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SearchActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SearchActivity.kt new file mode 100644 index 000000000..33901c1d4 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SearchActivity.kt @@ -0,0 +1,340 @@ +package com.simplemobiletools.gallery.pro.activities + +import android.app.SearchManager +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import android.view.ViewGroup +import android.widget.RelativeLayout +import androidx.appcompat.widget.SearchView +import androidx.core.view.MenuItemCompat +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.helpers.ensureBackgroundThread +import com.simplemobiletools.commons.models.FileDirItem +import com.simplemobiletools.commons.views.MyGridLayoutManager +import com.simplemobiletools.gallery.pro.R +import com.simplemobiletools.gallery.pro.adapters.MediaAdapter +import com.simplemobiletools.gallery.pro.asynctasks.GetMediaAsynctask +import com.simplemobiletools.gallery.pro.extensions.* +import com.simplemobiletools.gallery.pro.helpers.* +import com.simplemobiletools.gallery.pro.interfaces.MediaOperationsListener +import com.simplemobiletools.gallery.pro.models.Medium +import com.simplemobiletools.gallery.pro.models.ThumbnailItem +import com.simplemobiletools.gallery.pro.models.ThumbnailSection +import kotlinx.android.synthetic.main.activity_search.* +import java.io.File + +class SearchActivity : SimpleActivity(), MediaOperationsListener { + private var mIsSearchOpen = false + private var mLastSearchedText = "" + + private var mSearchMenuItem: MenuItem? = null + private var mCurrAsyncTask: GetMediaAsynctask? = null + private var mAllMedia = ArrayList() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_search) + media_empty_text_label.setTextColor(config.textColor) + getAllMedia() + } + + override fun onDestroy() { + super.onDestroy() + mCurrAsyncTask?.stopFetching() + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.menu_search, menu) + setupSearch(menu) + return true + } + + private fun setupSearch(menu: Menu) { + val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager + mSearchMenuItem = menu.findItem(R.id.search) + (mSearchMenuItem?.actionView as? SearchView)?.apply { + setSearchableInfo(searchManager.getSearchableInfo(componentName)) + isSubmitButtonEnabled = false + setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String) = false + + override fun onQueryTextChange(newText: String): Boolean { + if (mIsSearchOpen) { + mLastSearchedText = newText + textChanged(newText) + } + return true + } + }) + } + + MenuItemCompat.setOnActionExpandListener(mSearchMenuItem, object : MenuItemCompat.OnActionExpandListener { + override fun onMenuItemActionExpand(item: MenuItem?): Boolean { + mIsSearchOpen = true + return true + } + + // this triggers on device rotation too, avoid doing anything + override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { + if (mIsSearchOpen) { + mIsSearchOpen = false + mLastSearchedText = "" + } + return true + } + }) + mSearchMenuItem?.expandActionView() + } + + private fun textChanged(text: String) { + ensureBackgroundThread { + try { + val filtered = mAllMedia.filter { it is Medium && it.name.contains(text, true) } as ArrayList + filtered.sortBy { it is Medium && !it.name.startsWith(text, true) } + val grouped = MediaFetcher(applicationContext).groupMedia(filtered as ArrayList, "") + runOnUiThread { + if (grouped.isEmpty()) { + media_empty_text_label.text = getString(R.string.no_items_found) + media_empty_text_label.beVisible() + } else { + media_empty_text_label.beGone() + } + + getMediaAdapter()?.updateMedia(grouped) + measureRecyclerViewContent(grouped) + } + } catch (ignored: Exception) { + } + } + } + + private fun setupAdapter() { + val currAdapter = media_grid.adapter + if (currAdapter == null) { + val fastscroller = if (config.scrollHorizontally) media_horizontal_fastscroller else media_vertical_fastscroller + MediaAdapter(this, ArrayList(), this, false, false, "", media_grid, fastscroller) { + if (it is Medium) { + itemClicked(it.path) + } + }.apply { + media_grid.adapter = this + } + setupLayoutManager() + } else { + (currAdapter as MediaAdapter).updateMedia(mAllMedia) + } + + measureRecyclerViewContent(mAllMedia) + setupScrollDirection() + } + + private fun getMediaAdapter() = media_grid.adapter as? MediaAdapter + + private fun itemClicked(path: String) { + val isVideo = path.isVideoFast() + if (isVideo) { + openPath(path, false) + } else { + Intent(this, ViewPagerActivity::class.java).apply { + putExtra(PATH, path) + putExtra(SHOW_ALL, false) + startActivity(this) + } + } + } + + private fun setupLayoutManager() { + val viewType = config.getFolderViewType(SHOW_ALL) + if (viewType == VIEW_TYPE_GRID) { + setupGridLayoutManager() + } else { + setupListLayoutManager() + } + } + + private fun setupGridLayoutManager() { + val layoutManager = media_grid.layoutManager as MyGridLayoutManager + if (config.scrollHorizontally) { + layoutManager.orientation = RecyclerView.HORIZONTAL + media_grid.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT) + } else { + layoutManager.orientation = RecyclerView.VERTICAL + media_grid.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + } + + layoutManager.spanCount = config.mediaColumnCnt + val adapter = getMediaAdapter() + layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + return if (adapter?.isASectionTitle(position) == true) { + layoutManager.spanCount + } else { + 1 + } + } + } + } + + private fun setupListLayoutManager() { + val layoutManager = media_grid.layoutManager as MyGridLayoutManager + layoutManager.spanCount = 1 + layoutManager.orientation = RecyclerView.VERTICAL + } + + private fun setupScrollDirection() { + val viewType = config.getFolderViewType(SHOW_ALL) + val allowHorizontalScroll = config.scrollHorizontally && viewType == VIEW_TYPE_GRID + media_vertical_fastscroller.isHorizontal = false + media_vertical_fastscroller.beGoneIf(allowHorizontalScroll) + + media_horizontal_fastscroller.isHorizontal = true + media_horizontal_fastscroller.beVisibleIf(allowHorizontalScroll) + + val sorting = config.getFileSorting(SHOW_ALL) + if (allowHorizontalScroll) { + media_horizontal_fastscroller.allowBubbleDisplay = config.showInfoBubble + media_horizontal_fastscroller.setViews(media_grid) { + media_horizontal_fastscroller.updateBubbleText(getBubbleTextItem(it, sorting)) + } + } else { + media_vertical_fastscroller.allowBubbleDisplay = config.showInfoBubble + media_vertical_fastscroller.setViews(media_grid) { + media_vertical_fastscroller.updateBubbleText(getBubbleTextItem(it, sorting)) + } + } + } + + private fun getBubbleTextItem(index: Int, sorting: Int): String { + var realIndex = index + val mediaAdapter = getMediaAdapter() + if (mediaAdapter?.isASectionTitle(index) == true) { + realIndex++ + } + return mediaAdapter?.getItemBubbleText(realIndex, sorting) ?: "" + } + + private fun measureRecyclerViewContent(media: ArrayList) { + media_grid.onGlobalLayout { + if (config.scrollHorizontally) { + calculateContentWidth(media) + } else { + calculateContentHeight(media) + } + } + } + + private fun calculateContentWidth(media: ArrayList) { + val layoutManager = media_grid.layoutManager as MyGridLayoutManager + val thumbnailWidth = layoutManager.getChildAt(0)?.width ?: 0 + val fullWidth = ((media.size - 1) / layoutManager.spanCount + 1) * thumbnailWidth + media_horizontal_fastscroller.setContentWidth(fullWidth) + media_horizontal_fastscroller.setScrollToX(media_grid.computeHorizontalScrollOffset()) + } + + private fun calculateContentHeight(media: ArrayList) { + val layoutManager = media_grid.layoutManager as MyGridLayoutManager + val pathToCheck = SHOW_ALL + val hasSections = config.getFolderGrouping(pathToCheck) and GROUP_BY_NONE == 0 && !config.scrollHorizontally + val sectionTitleHeight = if (hasSections) layoutManager.getChildAt(0)?.height ?: 0 else 0 + val thumbnailHeight = if (hasSections) layoutManager.getChildAt(1)?.height ?: 0 else layoutManager.getChildAt(0)?.height ?: 0 + + var fullHeight = 0 + var curSectionItems = 0 + media.forEach { + if (it is ThumbnailSection) { + fullHeight += sectionTitleHeight + if (curSectionItems != 0) { + val rows = ((curSectionItems - 1) / layoutManager.spanCount + 1) + fullHeight += rows * thumbnailHeight + } + curSectionItems = 0 + } else { + curSectionItems++ + } + } + + fullHeight += ((curSectionItems - 1) / layoutManager.spanCount + 1) * thumbnailHeight + media_vertical_fastscroller.setContentHeight(fullHeight) + media_vertical_fastscroller.setScrollToY(media_grid.computeVerticalScrollOffset()) + } + + private fun getAllMedia() { + getCachedMedia("") { + if (it.isNotEmpty()) { + mAllMedia = it.clone() as ArrayList + } + runOnUiThread { + setupAdapter() + } + startAsyncTask(false) + } + } + + private fun startAsyncTask(updateItems: Boolean) { + mCurrAsyncTask?.stopFetching() + mCurrAsyncTask = GetMediaAsynctask(applicationContext, "", showAll = true) { + mAllMedia = it.clone() as ArrayList + if (updateItems) { + textChanged(mLastSearchedText) + } + } + + mCurrAsyncTask!!.execute() + } + + override fun refreshItems() { + startAsyncTask(true) + } + + override fun tryDeleteFiles(fileDirItems: ArrayList) { + val filtered = fileDirItems.filter { File(it.path).isFile && it.path.isMediaFile() } as ArrayList + if (filtered.isEmpty()) { + return + } + + if (config.useRecycleBin && !filtered.first().path.startsWith(recycleBinPath)) { + val movingItems = resources.getQuantityString(R.plurals.moving_items_into_bin, filtered.size, filtered.size) + toast(movingItems) + + movePathsInRecycleBin(filtered.map { it.path } as ArrayList, galleryDB.MediumDao()) { + if (it) { + deleteFilteredFiles(filtered) + } else { + toast(R.string.unknown_error_occurred) + } + } + } else { + val deletingItems = resources.getQuantityString(R.plurals.deleting_items, filtered.size, filtered.size) + toast(deletingItems) + deleteFilteredFiles(filtered) + } + } + + private fun deleteFilteredFiles(filtered: ArrayList) { + deleteFiles(filtered) { + if (!it) { + toast(R.string.unknown_error_occurred) + return@deleteFiles + } + + mAllMedia.removeAll { filtered.map { it.path }.contains((it as? Medium)?.path) } + + ensureBackgroundThread { + val useRecycleBin = config.useRecycleBin + filtered.forEach { + if (it.path.startsWith(recycleBinPath) || !useRecycleBin) { + deleteDBPath(galleryDB.MediumDao(), it.path) + } + } + } + } + } + + override fun selectedPaths(paths: ArrayList) { + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SetWallpaperActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SetWallpaperActivity.kt index 946e0176f..2ceafc06b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SetWallpaperActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SetWallpaperActivity.kt @@ -11,6 +11,7 @@ import android.view.Menu import android.view.MenuItem import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.extensions.toast +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.isNougatPlus import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.gallery.pro.R @@ -117,7 +118,7 @@ class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageComplete if (result.error == null) { toast(R.string.setting_wallpaper) - Thread { + ensureBackgroundThread { val bitmap = result.bitmap val wantedHeight = wallpaperManager.desiredMinimumHeight val ratio = wantedHeight / bitmap.height.toFloat() @@ -135,7 +136,7 @@ class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageComplete setResult(Activity.RESULT_CANCELED) } finish() - }.start() + } } else { toast("${getString(R.string.image_editing_failed)}: ${result.error.message}") } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SettingsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SettingsActivity.kt index a8df6dc58..c1e278770 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SettingsActivity.kt @@ -572,7 +572,7 @@ class SettingsActivity : SimpleActivity() { } private fun setupEmptyRecycleBin() { - Thread { + ensureBackgroundThread { try { mRecycleBinContentSize = galleryDB.MediumDao().getDeletedMedia().sumByLong { it.size } } catch (ignored: Exception) { @@ -580,7 +580,7 @@ class SettingsActivity : SimpleActivity() { runOnUiThread { settings_empty_recycle_bin_size.text = mRecycleBinContentSize.formatSize() } - }.start() + } settings_empty_recycle_bin_holder.setOnClickListener { if (mRecycleBinContentSize == 0L) { @@ -686,13 +686,13 @@ class SettingsActivity : SimpleActivity() { private fun setupImportSettings() { settings_import_holder.setOnClickListener { FilePickerDialog(this) { - Thread { + ensureBackgroundThread { try { parseFile(it) } catch (e: Exception) { showErrorToast(e) } - }.start() + } } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SimpleActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SimpleActivity.kt index 2be7d90fe..da2a95982 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SimpleActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/SimpleActivity.kt @@ -6,11 +6,16 @@ import android.net.Uri import android.provider.MediaStore import android.view.WindowManager import com.simplemobiletools.commons.activities.BaseSimpleActivity +import com.simplemobiletools.commons.dialogs.FilePickerDialog +import com.simplemobiletools.commons.extensions.getParentPath import com.simplemobiletools.commons.extensions.getRealPathFromURI +import com.simplemobiletools.commons.extensions.scanPathRecursively +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.isPiePlus import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.extensions.addPathToDB import com.simplemobiletools.gallery.pro.extensions.config +import com.simplemobiletools.gallery.pro.extensions.updateDirectoryPath open class SimpleActivity : BaseSimpleActivity() { val observer = object : ContentObserver(null) { @@ -18,6 +23,7 @@ open class SimpleActivity : BaseSimpleActivity() { super.onChange(selfChange, uri) val path = getRealPathFromURI(uri) if (path != null) { + updateDirectoryPath(path.getParentPath()) addPathToDB(path) } } @@ -76,4 +82,15 @@ open class SimpleActivity : BaseSimpleActivity() { } catch (ignored: Exception) { } } + + protected fun showAddIncludedFolderDialog(callback: () -> Unit) { + FilePickerDialog(this, config.lastFilepickerPath, false, config.shouldShowHidden, false, true) { + config.lastFilepickerPath = it + config.addIncludedFolder(it) + callback() + ensureBackgroundThread { + scanPathRecursively(it) + } + } + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt index a1f0c225e..bed9bc018 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/VideoPlayerActivity.kt @@ -25,6 +25,7 @@ import com.google.android.exoplayer2.upstream.DataSpec import com.google.android.exoplayer2.video.VideoListener import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.extensions.* import com.simplemobiletools.gallery.pro.helpers.* @@ -566,10 +567,10 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen private fun releaseExoPlayer() { mExoPlayer?.stop() - Thread { + ensureBackgroundThread { mExoPlayer?.release() mExoPlayer = null - }.start() + } } override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { @@ -602,9 +603,9 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?) = false override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) { - Thread { + ensureBackgroundThread { mExoPlayer?.setVideoSurface(Surface(video_surface!!.surfaceTexture)) - }.start() + } } override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {} diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt index 6ba9995da..e6418911f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt @@ -2,13 +2,18 @@ package com.simplemobiletools.gallery.pro.activities import android.animation.Animator import android.animation.ValueAnimator +import android.annotation.SuppressLint import android.app.Activity import android.content.Intent import android.content.pm.ActivityInfo +import android.content.pm.ShortcutInfo +import android.content.pm.ShortcutManager import android.content.res.Configuration import android.database.Cursor +import android.graphics.Bitmap import android.graphics.Color import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Icon import android.media.ExifInterface import android.net.Uri import android.os.Bundle @@ -20,7 +25,15 @@ import android.view.View import android.view.WindowManager import android.view.animation.DecelerateInterpolator import android.widget.Toast +import androidx.print.PrintHelper import androidx.viewpager.widget.ViewPager +import com.bumptech.glide.Glide +import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.engine.DiskCacheStrategy +import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.request.target.Target import com.simplemobiletools.commons.dialogs.PropertiesDialog import com.simplemobiletools.commons.dialogs.RenameItemDialog import com.simplemobiletools.commons.extensions.* @@ -66,6 +79,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View private var mMediaFiles = ArrayList() private var mFavoritePaths = ArrayList() + private var mIgnoredPaths = ArrayList() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -155,11 +169,13 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View findItem(R.id.menu_copy_to).isVisible = visibleBottomActions and BOTTOM_ACTION_COPY == 0 findItem(R.id.menu_move_to).isVisible = visibleBottomActions and BOTTOM_ACTION_MOVE == 0 findItem(R.id.menu_save_as).isVisible = rotationDegrees != 0 + findItem(R.id.menu_print).isVisible = currentMedium.isImage() || currentMedium.isRaw() findItem(R.id.menu_hide).isVisible = !currentMedium.isHidden() && visibleBottomActions and BOTTOM_ACTION_TOGGLE_VISIBILITY == 0 && !currentMedium.getIsInRecycleBin() findItem(R.id.menu_unhide).isVisible = currentMedium.isHidden() && visibleBottomActions and BOTTOM_ACTION_TOGGLE_VISIBILITY == 0 && !currentMedium.getIsInRecycleBin() - findItem(R.id.menu_add_to_favorites).isVisible = !currentMedium.isFavorite && visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE == 0 - findItem(R.id.menu_remove_from_favorites).isVisible = currentMedium.isFavorite && visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE == 0 + findItem(R.id.menu_add_to_favorites).isVisible = !currentMedium.isFavorite && visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE == 0 && !currentMedium.getIsInRecycleBin() + findItem(R.id.menu_remove_from_favorites).isVisible = currentMedium.isFavorite && visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE == 0 && !currentMedium.getIsInRecycleBin() findItem(R.id.menu_restore_file).isVisible = currentMedium.path.startsWith(recycleBinPath) + findItem(R.id.menu_create_shortcut).isVisible = isOreoPlus() findItem(R.id.menu_change_orientation).isVisible = rotationDegrees == 0 && visibleBottomActions and BOTTOM_ACTION_CHANGE_ORIENTATION == 0 findItem(R.id.menu_change_orientation).icon = resources.getDrawable(getChangeOrientationIcon()) findItem(R.id.menu_rotate).setShowAsAction( @@ -191,6 +207,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View R.id.menu_share -> shareMediumPath(getCurrentPath()) R.id.menu_delete -> checkDeleteConfirmation() R.id.menu_rename -> renameFile() + R.id.menu_print -> printFile() R.id.menu_edit -> openEditor(getCurrentPath()) R.id.menu_properties -> showProperties() R.id.menu_show_on_map -> showOnMap() @@ -204,6 +221,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View R.id.menu_force_landscape -> toggleOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) R.id.menu_default_orientation -> toggleOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) R.id.menu_save_as -> saveImageAs() + R.id.menu_create_shortcut -> createShortcut() R.id.menu_settings -> launchSettings() else -> return super.onOptionsItemSelected(item) } @@ -317,8 +335,9 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } if (intent.action == "com.android.camera.action.REVIEW") { - Thread { - if (galleryDB.MediumDao().getMediaFromPath(mPath).isEmpty()) { + ensureBackgroundThread { + val mediumDao = galleryDB.MediumDao() + if (mediumDao.getMediaFromPath(mPath).isEmpty()) { val type = when { mPath.isVideoFast() -> TYPE_VIDEOS mPath.isGif() -> TYPE_GIFS @@ -327,11 +346,13 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View else -> TYPE_IMAGES } + val isFavorite = mediumDao.isFavorite(mPath) val duration = if (type == TYPE_VIDEOS) mPath.getVideoDuration() else 0 - val medium = Medium(null, mPath.getFilenameFromPath(), mPath, mPath.getParentPath(), System.currentTimeMillis(), System.currentTimeMillis(), File(mPath).length(), type, duration, false, 0) - galleryDB.MediumDao().insert(medium) + val ts = System.currentTimeMillis() + val medium = Medium(null, mPath.getFilenameFromPath(), mPath, mPath.getParentPath(), ts, ts, File(mPath).length(), type, duration, isFavorite, 0) + mediumDao.insert(medium) } - }.start() + } } } @@ -341,9 +362,9 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } private fun initFavorites() { - Thread { + ensureBackgroundThread { mFavoritePaths = getFavoritePaths() - }.start() + } } private fun setupOrientation() { @@ -359,8 +380,10 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View private fun updatePagerItems(media: MutableList) { val pagerAdapter = MyPagerAdapter(this, supportFragmentManager, media) if (!isDestroyed) { + pagerAdapter.shouldInitFragment = mPos < 5 view_pager.apply { adapter = pagerAdapter + pagerAdapter.shouldInitFragment = true currentItem = mPos removeOnPageChangeListener(this@ViewPagerActivity) addOnPageChangeListener(this@ViewPagerActivity) @@ -384,6 +407,10 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View if (getMediaForSlideshow()) { view_pager.onGlobalLayout { if (!isDestroyed) { + if (config.slideshowAnimation == SLIDESHOW_ANIMATION_FADE) { + view_pager.setPageTransformer(false, FadePageTransformer()) + } + hideSystemUI(true) mSlideshowInterval = config.slideshowInterval mSlideshowMoveBackwards = config.slideshowMoveBackwards @@ -395,6 +422,16 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } } + private fun goToNextMedium(forward: Boolean) { + val oldPosition = view_pager.currentItem + val newPosition = if (forward) oldPosition + 1 else oldPosition - 1 + if (newPosition == -1 || newPosition > view_pager.adapter!!.count - 1) { + slideshowEnded(forward) + } else { + view_pager.setCurrentItem(newPosition, false) + } + } + private fun animatePagerTransition(forward: Boolean) { val oldPosition = view_pager.currentItem val animator = ValueAnimator.ofInt(0, view_pager.width) @@ -424,7 +461,13 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } }) - animator.interpolator = DecelerateInterpolator() + if (config.slideshowAnimation == SLIDESHOW_ANIMATION_SLIDE) { + animator.interpolator = DecelerateInterpolator() + animator.duration = SLIDESHOW_SLIDE_DURATION + } else { + animator.duration = SLIDESHOW_FADE_DURATION + } + animator.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener { var oldDragPosition = 0 override fun onAnimationUpdate(animation: ValueAnimator) { @@ -441,7 +484,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } }) - animator.duration = SLIDESHOW_SCROLL_DURATION view_pager.beginFakeDrag() animator.start() } @@ -461,6 +503,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View private fun stopSlideshow() { if (mIsSlideshowActive) { + view_pager.setPageTransformer(false, DefaultPageTransformer()) mIsSlideshowActive = false showSystemUI(true) mSlideshowHandler.removeCallbacksAndMessages(null) @@ -484,7 +527,11 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } private fun swipeToNextMedium() { - animatePagerTransition(!mSlideshowMoveBackwards) + if (config.slideshowAnimation == SLIDESHOW_ANIMATION_NONE) { + goToNextMedium(!mSlideshowMoveBackwards) + } else { + animatePagerTransition(!mSlideshowMoveBackwards) + } } private fun getMediaForSlideshow(): Boolean { @@ -588,14 +635,37 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View val newPath = it handleSAFDialog(it) { toast(R.string.saving) - Thread { - val photoFragment = getCurrentPhotoFragment() ?: return@Thread + ensureBackgroundThread { + val photoFragment = getCurrentPhotoFragment() ?: return@ensureBackgroundThread saveRotatedImageToFile(currPath, newPath, photoFragment.mCurrentRotationDegrees, true) { toast(R.string.file_saved) getCurrentPhotoFragment()?.mCurrentRotationDegrees = 0 invalidateOptionsMenu() } - }.start() + } + } + } + } + + @SuppressLint("NewApi") + private fun createShortcut() { + val manager = getSystemService(ShortcutManager::class.java) + if (manager.isRequestPinShortcutSupported) { + val medium = getCurrentMedium() ?: return + val path = medium.path + val drawable = resources.getDrawable(R.drawable.shortcut_image).mutate() + getShortcutImage(path, drawable) { + val intent = Intent(this, PhotoVideoActivity::class.java) + intent.action = Intent.ACTION_VIEW + intent.data = Uri.fromFile(File(path)) + + val shortcut = ShortcutInfo.Builder(this, path) + .setShortLabel(medium.name) + .setIcon(Icon.createWithBitmap(drawable.convertToBitmap())) + .setIntent(intent) + .build() + + manager.requestPinShortcut(shortcut, null) } } } @@ -704,13 +774,14 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } private fun initBottomActionButtons() { + val currentMedium = getCurrentMedium() val visibleBottomActions = if (config.bottomActions) config.visibleBottomActions else 0 - bottom_favorite.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE != 0) + bottom_favorite.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_TOGGLE_FAVORITE != 0 && currentMedium?.getIsInRecycleBin() == false) bottom_favorite.setOnClickListener { toggleFavorite() } - bottom_edit.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_EDIT != 0 && getCurrentMedium()?.isSVG() == false) + bottom_edit.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_EDIT != 0 && currentMedium?.isSVG() == false) bottom_edit.setOnClickListener { openEditor(getCurrentPath()) } @@ -742,7 +813,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View else -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } mIsOrientationLocked = requestedOrientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - updateBottomActionIcons(getCurrentMedium()) + updateBottomActionIcons(currentMedium) } bottom_slideshow.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_SLIDESHOW != 0) @@ -757,14 +828,14 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View bottom_toggle_file_visibility.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_TOGGLE_VISIBILITY != 0) bottom_toggle_file_visibility.setOnClickListener { - getCurrentMedium()?.apply { + currentMedium?.apply { toggleFileVisibility(!isHidden()) { - updateBottomActionIcons(getCurrentMedium()) + updateBottomActionIcons(currentMedium) } } } - bottom_rename.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_RENAME != 0 && getCurrentMedium()?.getIsInRecycleBin() == false) + bottom_rename.beVisibleIf(visibleBottomActions and BOTTOM_ACTION_RENAME != 0 && currentMedium?.getIsInRecycleBin() == false) bottom_rename.setOnClickListener { renameFile() } @@ -803,7 +874,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View private fun toggleFavorite() { val medium = getCurrentMedium() ?: return medium.isFavorite = !medium.isFavorite - Thread { + ensureBackgroundThread { galleryDB.MediumDao().updateFavorite(medium.path, medium.isFavorite) if (medium.isFavorite) { mFavoritePaths.add(medium.path) @@ -811,7 +882,60 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View mFavoritePaths.remove(medium.path) } invalidateOptionsMenu() - }.start() + } + } + + private fun printFile() { + sendPrintIntent(getCurrentPath()) + } + + private fun sendPrintIntent(path: String) { + val printHelper = PrintHelper(this) + printHelper.scaleMode = PrintHelper.SCALE_MODE_FIT + printHelper.orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + + try { + val resolution = path.getImageResolution() + if (resolution == null) { + toast(R.string.unknown_error_occurred) + return + } + + var requestedWidth = resolution.x + var requestedHeight = resolution.y + + if (requestedWidth >= MAX_PRINT_SIDE_SIZE) { + requestedHeight = (requestedHeight / (requestedWidth / MAX_PRINT_SIDE_SIZE.toFloat())).toInt() + requestedWidth = MAX_PRINT_SIDE_SIZE + } else if (requestedHeight >= MAX_PRINT_SIDE_SIZE) { + requestedWidth = (requestedWidth / (requestedHeight / MAX_PRINT_SIDE_SIZE.toFloat())).toInt() + requestedHeight = MAX_PRINT_SIDE_SIZE + } + + val options = RequestOptions() + .skipMemoryCache(true) + .diskCacheStrategy(DiskCacheStrategy.NONE) + + Glide.with(this) + .asBitmap() + .load(path) + .apply(options) + .listener(object : RequestListener { + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { + showErrorToast(e?.localizedMessage ?: "") + return false + } + + override fun onResourceReady(bitmap: Bitmap?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { + if (bitmap != null) { + printHelper.printBitmap(path.getFilenameFromPath(), bitmap) + } + + return false + } + }).submit(requestedWidth, requestedHeight) + } catch (e: Exception) { + } } private fun restoreFile() { @@ -877,19 +1001,37 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View val fileDirItem = FileDirItem(path, path.getFilenameFromPath()) if (config.useRecycleBin && !getCurrentMedium()!!.getIsInRecycleBin()) { + mIgnoredPaths.add(fileDirItem.path) + val media = mMediaFiles.filter { !mIgnoredPaths.contains(it.path) } as ArrayList + runOnUiThread { + gotMedia(media) + } + movePathsInRecycleBin(arrayListOf(path)) { if (it) { tryDeleteFileDirItem(fileDirItem, false, false) { - refreshViewPager() + mIgnoredPaths.remove(fileDirItem.path) + deleteDirectoryIfEmpty() } } else { toast(R.string.unknown_error_occurred) } } } else { - tryDeleteFileDirItem(fileDirItem, false, true) { - refreshViewPager() - } + handleDeletion(fileDirItem) + } + } + + private fun handleDeletion(fileDirItem: FileDirItem) { + mIgnoredPaths.add(fileDirItem.path) + val media = mMediaFiles.filter { !mIgnoredPaths.contains(it.path) } as ArrayList + runOnUiThread { + gotMedia(media) + } + + tryDeleteFileDirItem(fileDirItem, false, true) { + mIgnoredPaths.remove(fileDirItem.path) + deleteDirectoryIfEmpty() } } @@ -911,9 +1053,9 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View name = it.getFilenameFromPath() } - Thread { + ensureBackgroundThread { updateDBMediaPath(oldPath, it) - }.start() + } updateActionbarTitle() } } @@ -932,7 +1074,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } private fun gotMedia(thumbnailItems: ArrayList) { - val media = thumbnailItems.asSequence().filter { it is Medium }.map { it as Medium }.toMutableList() as ArrayList + val media = thumbnailItems.asSequence().filter { it is Medium && !mIgnoredPaths.contains(it.path) }.map { it as Medium }.toMutableList() as ArrayList if (isDirEmpty(media) || media.hashCode() == mPrevHashcode) { return } @@ -966,9 +1108,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View val fileDirItem = FileDirItem(mDirectory, mDirectory.getFilenameFromPath(), File(mDirectory).isDirectory) if (config.deleteEmptyFolders && !fileDirItem.isDownloadsFolder() && fileDirItem.isDirectory && fileDirItem.getProperFileCount(true) == 0) { tryDeleteFileDirItem(fileDirItem, true, true) + scanPathRecursively(mDirectory) } - - scanPathRecursively(mDirectory) } private fun checkOrientation() { @@ -976,8 +1117,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View var flipSides = false try { val pathToLoad = getCurrentPath() - val exif = android.media.ExifInterface(pathToLoad) - val orientation = exif.getAttributeInt(android.media.ExifInterface.TAG_ORIENTATION, -1) + val exif = ExifInterface(pathToLoad) + val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1) flipSides = orientation == ExifInterface.ORIENTATION_ROTATE_90 || orientation == ExifInterface.ORIENTATION_ROTATE_270 } catch (e: Exception) { } @@ -1015,8 +1156,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } override fun launchViewVideoIntent(path: String) { - Thread { - val newUri = getFinalUriFromPath(path, BuildConfig.APPLICATION_ID) ?: return@Thread + ensureBackgroundThread { + val newUri = getFinalUriFromPath(path, BuildConfig.APPLICATION_ID) ?: return@ensureBackgroundThread val mimeType = getUriMimeType(path, newUri) Intent().apply { action = Intent.ACTION_VIEW @@ -1039,7 +1180,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } } } - }.start() + } } private fun checkSystemUI() { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/WidgetConfigureActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/WidgetConfigureActivity.kt index 20feaa695..f34a23e9b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/WidgetConfigureActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/WidgetConfigureActivity.kt @@ -10,6 +10,7 @@ import android.widget.RelativeLayout import android.widget.RemoteViews import com.simplemobiletools.commons.dialogs.ColorPickerDialog import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.dialogs.PickDirectoryDialog import com.simplemobiletools.gallery.pro.extensions.* @@ -89,9 +90,9 @@ class WidgetConfigureActivity : SimpleActivity() { AppWidgetManager.getInstance(this).updateAppWidget(mWidgetId, views) config.showWidgetFolderName = folder_picker_show_folder_name.isChecked val widget = Widget(null, mWidgetId, mFolderPath) - Thread { + ensureBackgroundThread { widgetsDB.insertOrUpdate(widget) - }.start() + } storeWidgetColors() requestWidgetUpdate() @@ -161,14 +162,14 @@ class WidgetConfigureActivity : SimpleActivity() { config_folder_name.text = getFolderNameFromPath(folderPath) } - Thread { + ensureBackgroundThread { val path = directoryDB.getDirectoryThumbnail(folderPath) if (path != null) { runOnUiThread { loadJpg(path, config_image, config.cropThumbnails) } } - }.start() + } } private fun handleFolderNameDisplay() { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/DirectoryAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/DirectoryAdapter.kt index c0c39db89..2d3256258 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/DirectoryAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/DirectoryAdapter.kt @@ -1,5 +1,10 @@ package com.simplemobiletools.gallery.pro.adapters +import android.annotation.SuppressLint +import android.content.Intent +import android.content.pm.ShortcutInfo +import android.content.pm.ShortcutManager +import android.graphics.drawable.Icon import android.view.Menu import android.view.View import android.view.ViewGroup @@ -12,10 +17,14 @@ import com.simplemobiletools.commons.dialogs.PropertiesDialog import com.simplemobiletools.commons.dialogs.RenameItemDialog import com.simplemobiletools.commons.dialogs.RenameItemsDialog import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.helpers.ensureBackgroundThread +import com.simplemobiletools.commons.helpers.isOreoPlus import com.simplemobiletools.commons.models.FileDirItem import com.simplemobiletools.commons.views.FastScroller import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.gallery.pro.R +import com.simplemobiletools.gallery.pro.activities.MediaActivity +import com.simplemobiletools.gallery.pro.dialogs.ConfirmDeleteFolderDialog import com.simplemobiletools.gallery.pro.dialogs.ExcludeFolderDialog import com.simplemobiletools.gallery.pro.dialogs.PickMediumDialog import com.simplemobiletools.gallery.pro.extensions.* @@ -75,6 +84,8 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList copyMoveTo(true) R.id.cab_move_to -> moveFilesTo() R.id.cab_select_all -> selectAll() + R.id.cab_create_shortcut -> createShortcut() R.id.cab_delete -> askConfirmDelete() R.id.cab_select_photo -> changeAlbumCover(false) R.id.cab_use_default -> changeAlbumCover(true) @@ -159,10 +171,10 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList activity.handleDeletePasswordProtection { @@ -349,7 +386,11 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList { val itemsCnt = selectedKeys.size val items = if (itemsCnt == 1) { - "\"${getSelectedPaths().first().getFilenameFromPath()}\"" + var folder = getSelectedPaths().first().getFilenameFromPath() + if (folder == RECYCLE_BIN) { + folder = activity.getString(R.string.recycle_bin) + } + "\"$folder\"" } else { resources.getQuantityString(R.plurals.delete_items, itemsCnt, itemsCnt) } @@ -361,10 +402,9 @@ class DirectoryAdapter(activity: BaseSimpleActivity, var dirs: ArrayList + val isInRecycleBin = selectedItems.firstOrNull()?.getIsInRecycleBin() == true menu.apply { - findItem(R.id.cab_rename).isVisible = selectedItems.firstOrNull()?.getIsInRecycleBin() == false + findItem(R.id.cab_rename).isVisible = !isInRecycleBin + findItem(R.id.cab_add_to_favorites).isVisible = !isInRecycleBin + findItem(R.id.cab_fix_date_taken).isVisible = !isInRecycleBin + findItem(R.id.cab_move_to).isVisible = !isInRecycleBin findItem(R.id.cab_open_with).isVisible = isOneItemSelected findItem(R.id.cab_confirm_selection).isVisible = isAGetIntent && allowMultiplePicks && selectedKeys.isNotEmpty() findItem(R.id.cab_restore_recycle_bin_files).isVisible = selectedPaths.all { it.startsWith(activity.recycleBinPath) } @@ -178,8 +182,8 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList) { - menu.findItem(R.id.cab_add_to_favorites).isVisible = selectedItems.any { !it.isFavorite } - menu.findItem(R.id.cab_remove_from_favorites).isVisible = selectedItems.any { it.isFavorite } + menu.findItem(R.id.cab_add_to_favorites).isVisible = selectedItems.none { it.getIsInRecycleBin() } && selectedItems.any { !it.isFavorite } + menu.findItem(R.id.cab_remove_from_favorites).isVisible = selectedItems.none { it.getIsInRecycleBin() } && selectedItems.any { it.isFavorite } } private fun confirmSelection() { @@ -200,7 +204,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList) : FragmentStatePagerAdapter(fm) { private val fragments = HashMap() + var shouldInitFragment = true + override fun getCount() = media.size override fun getItem(position: Int): Fragment { val medium = media[position] val bundle = Bundle() bundle.putSerializable(MEDIUM, medium) + bundle.putBoolean(SHOULD_INIT_FRAGMENT, shouldInitFragment) val fragment = if (medium.isVideo()) { VideoFragment() } else { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/asynctasks/GetMediaAsynctask.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/asynctasks/GetMediaAsynctask.kt index d382422a4..5c21358cc 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/asynctasks/GetMediaAsynctask.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/asynctasks/GetMediaAsynctask.kt @@ -18,7 +18,7 @@ class GetMediaAsynctask(val context: Context, val mPath: String, val isPickImage override fun doInBackground(vararg params: Void): ArrayList { val pathToUse = if (showAll) SHOW_ALL else mPath - val getProperDateTaken = context.config.getFileSorting(pathToUse) and SORT_BY_DATE_TAKEN != 0 || context.config.getFolderGrouping(pathToUse) and GROUP_BY_DATE_TAKEN != 0 + val getProperDateTaken = context.config.getFileSorting(pathToUse) and SORT_BY_DATE_TAKEN != 0 || context.config.getFolderGrouping(pathToUse) and GROUP_BY_DATE_TAKEN_DAILY != 0 val getProperFileSize = context.config.getFileSorting(pathToUse) and SORT_BY_SIZE != 0 val favoritePaths = context.getFavoritePaths() val getVideoDurations = context.config.showThumbnailVideoDuration diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ChangeGroupingDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ChangeGroupingDialog.kt index 90d1bdf6c..71da2f57d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ChangeGroupingDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ChangeGroupingDialog.kt @@ -41,8 +41,10 @@ class ChangeGroupingDialog(val activity: BaseSimpleActivity, val path: String = val groupBtn = when { currGrouping and GROUP_BY_NONE != 0 -> groupingRadio.grouping_dialog_radio_none - currGrouping and GROUP_BY_LAST_MODIFIED != 0 -> groupingRadio.grouping_dialog_radio_last_modified - currGrouping and GROUP_BY_DATE_TAKEN != 0 -> groupingRadio.grouping_dialog_radio_date_taken + currGrouping and GROUP_BY_LAST_MODIFIED_DAILY != 0 -> groupingRadio.grouping_dialog_radio_last_modified_daily + currGrouping and GROUP_BY_LAST_MODIFIED_MONTHLY != 0 -> groupingRadio.grouping_dialog_radio_last_modified_monthly + currGrouping and GROUP_BY_DATE_TAKEN_DAILY != 0 -> groupingRadio.grouping_dialog_radio_date_taken_daily + currGrouping and GROUP_BY_DATE_TAKEN_MONTHLY != 0 -> groupingRadio.grouping_dialog_radio_date_taken_monthly currGrouping and GROUP_BY_FILE_TYPE != 0 -> groupingRadio.grouping_dialog_radio_file_type currGrouping and GROUP_BY_EXTENSION != 0 -> groupingRadio.grouping_dialog_radio_extension else -> groupingRadio.grouping_dialog_radio_folder @@ -64,8 +66,10 @@ class ChangeGroupingDialog(val activity: BaseSimpleActivity, val path: String = val groupingRadio = view.grouping_dialog_radio_grouping var grouping = when (groupingRadio.checkedRadioButtonId) { R.id.grouping_dialog_radio_none -> GROUP_BY_NONE - R.id.grouping_dialog_radio_last_modified -> GROUP_BY_LAST_MODIFIED - R.id.grouping_dialog_radio_date_taken -> GROUP_BY_DATE_TAKEN + R.id.grouping_dialog_radio_last_modified_daily -> GROUP_BY_LAST_MODIFIED_DAILY + R.id.grouping_dialog_radio_last_modified_monthly -> GROUP_BY_LAST_MODIFIED_MONTHLY + R.id.grouping_dialog_radio_date_taken_daily -> GROUP_BY_DATE_TAKEN_DAILY + R.id.grouping_dialog_radio_date_taken_monthly -> GROUP_BY_DATE_TAKEN_MONTHLY R.id.grouping_dialog_radio_file_type -> GROUP_BY_FILE_TYPE R.id.grouping_dialog_radio_extension -> GROUP_BY_EXTENSION else -> GROUP_BY_FOLDER diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ChangeSortingDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ChangeSortingDialog.kt index 79c0961a6..9db8e7b13 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ChangeSortingDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ChangeSortingDialog.kt @@ -5,6 +5,7 @@ import android.view.View import androidx.appcompat.app.AlertDialog import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.extensions.beVisibleIf +import com.simplemobiletools.commons.extensions.isVisible import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.gallery.pro.R @@ -12,7 +13,7 @@ import com.simplemobiletools.gallery.pro.extensions.config import com.simplemobiletools.gallery.pro.helpers.SHOW_ALL import kotlinx.android.synthetic.main.dialog_change_sorting.view.* -class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorting: Boolean, showFolderCheckbox: Boolean, +class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorting: Boolean, val showFolderCheckbox: Boolean, val path: String = "", val callback: () -> Unit) : DialogInterface.OnClickListener { private var currSorting = 0 @@ -21,11 +22,16 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorti private var view: View init { + currSorting = if (isDirectorySorting) config.directorySorting else config.getFileSorting(pathToUse) view = activity.layoutInflater.inflate(R.layout.dialog_change_sorting, null).apply { - use_for_this_folder_divider.beVisibleIf(showFolderCheckbox) + use_for_this_folder_divider.beVisibleIf(showFolderCheckbox || (currSorting and SORT_BY_NAME != 0 || currSorting and SORT_BY_PATH != 0)) + + sorting_dialog_numeric_sorting.beVisibleIf(showFolderCheckbox && (currSorting and SORT_BY_NAME != 0 || currSorting and SORT_BY_PATH != 0)) + sorting_dialog_numeric_sorting.isChecked = currSorting and SORT_USE_NUMERIC_VALUE != 0 + sorting_dialog_use_for_this_folder.beVisibleIf(showFolderCheckbox) - sorting_dialog_bottom_note.beVisibleIf(!isDirectorySorting) sorting_dialog_use_for_this_folder.isChecked = config.hasCustomSorting(pathToUse) + sorting_dialog_bottom_note.beVisibleIf(!isDirectorySorting) } AlertDialog.Builder(activity) @@ -35,13 +41,17 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorti activity.setupDialogStuff(view, this, R.string.sort_by) } - currSorting = if (isDirectorySorting) config.directorySorting else config.getFileSorting(pathToUse) setupSortRadio() setupOrderRadio() } private fun setupSortRadio() { val sortingRadio = view.sorting_dialog_radio_sorting + sortingRadio.setOnCheckedChangeListener { group, checkedId -> + val isSortingByNameOrPath = checkedId == sortingRadio.sorting_dialog_radio_name.id || checkedId == sortingRadio.sorting_dialog_radio_path.id + view.sorting_dialog_numeric_sorting.beVisibleIf(isSortingByNameOrPath) + view.use_for_this_folder_divider.beVisibleIf(view.sorting_dialog_numeric_sorting.isVisible() || view.sorting_dialog_use_for_this_folder.isVisible()) + } val sortBtn = when { currSorting and SORT_BY_PATH != 0 -> sortingRadio.sorting_dialog_radio_path @@ -79,6 +89,10 @@ class ChangeSortingDialog(val activity: BaseSimpleActivity, val isDirectorySorti sorting = sorting or SORT_DESCENDING } + if (view.sorting_dialog_numeric_sorting.isChecked) { + sorting = sorting or SORT_USE_NUMERIC_VALUE + } + if (isDirectorySorting) { config.directorySorting = sorting } else { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ConfirmDeleteFolderDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ConfirmDeleteFolderDialog.kt new file mode 100644 index 000000000..27f3a59c9 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ConfirmDeleteFolderDialog.kt @@ -0,0 +1,31 @@ +package com.simplemobiletools.gallery.pro.dialogs + +import android.app.Activity +import androidx.appcompat.app.AlertDialog +import com.simplemobiletools.commons.extensions.setupDialogStuff +import com.simplemobiletools.gallery.pro.R +import kotlinx.android.synthetic.main.dialog_confirm_delete_folder.view.* + +class ConfirmDeleteFolderDialog(activity: Activity, message: String, warningMessage: String, val callback: () -> Unit) { + var dialog: AlertDialog + + init { + val view = activity.layoutInflater.inflate(R.layout.dialog_confirm_delete_folder, null) + view.message.text = message + view.message_warning.text = warningMessage + + val builder = AlertDialog.Builder(activity) + .setPositiveButton(R.string.yes) { dialog, which -> dialogConfirmed() } + + builder.setNegativeButton(R.string.no, null) + + dialog = builder.create().apply { + activity.setupDialogStuff(view, this) + } + } + + private fun dialogConfirmed() { + dialog.dismiss() + callback() + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/SlideshowDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/SlideshowDialog.kt index 7ab0371a8..66d57fef9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/SlideshowDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/SlideshowDialog.kt @@ -3,10 +3,16 @@ package com.simplemobiletools.gallery.pro.dialogs import android.view.View import androidx.appcompat.app.AlertDialog import com.simplemobiletools.commons.activities.BaseSimpleActivity +import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.extensions.hideKeyboard import com.simplemobiletools.commons.extensions.setupDialogStuff +import com.simplemobiletools.commons.extensions.value +import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.extensions.config +import com.simplemobiletools.gallery.pro.helpers.SLIDESHOW_ANIMATION_FADE +import com.simplemobiletools.gallery.pro.helpers.SLIDESHOW_ANIMATION_NONE +import com.simplemobiletools.gallery.pro.helpers.SLIDESHOW_ANIMATION_SLIDE import com.simplemobiletools.gallery.pro.helpers.SLIDESHOW_DEFAULT_INTERVAL import kotlinx.android.synthetic.main.dialog_slideshow.view.* @@ -28,6 +34,18 @@ class SlideshowDialog(val activity: BaseSimpleActivity, val callback: () -> Unit activity.hideKeyboard(v) } + animation_holder.setOnClickListener { + val items = arrayListOf( + RadioItem(SLIDESHOW_ANIMATION_NONE, activity.getString(R.string.no_animation)), + RadioItem(SLIDESHOW_ANIMATION_SLIDE, activity.getString(R.string.slide)), + RadioItem(SLIDESHOW_ANIMATION_FADE, activity.getString(R.string.fade))) + + RadioGroupDialog(activity, items, activity.config.slideshowAnimation) { + activity.config.slideshowAnimation = it as Int + animation_value.text = getAnimationText() + } + } + include_videos_holder.setOnClickListener { interval_value.clearFocus() include_videos.toggle() @@ -43,11 +61,6 @@ class SlideshowDialog(val activity: BaseSimpleActivity, val callback: () -> Unit random_order.toggle() } - use_fade_holder.setOnClickListener { - interval_value.clearFocus() - use_fade.toggle() - } - move_backwards_holder.setOnClickListener { interval_value.clearFocus() move_backwards.toggle() @@ -79,10 +92,10 @@ class SlideshowDialog(val activity: BaseSimpleActivity, val callback: () -> Unit val config = activity.config view.apply { interval_value.setText(config.slideshowInterval.toString()) + animation_value.text = getAnimationText() include_videos.isChecked = config.slideshowIncludeVideos include_gifs.isChecked = config.slideshowIncludeGIFs random_order.isChecked = config.slideshowRandomOrder - use_fade.isChecked = config.slideshowUseFade move_backwards.isChecked = config.slideshowMoveBackwards loop_slideshow.isChecked = config.loopSlideshow } @@ -94,13 +107,29 @@ class SlideshowDialog(val activity: BaseSimpleActivity, val callback: () -> Unit interval = SLIDESHOW_DEFAULT_INTERVAL.toString() activity.config.apply { + slideshowAnimation = getAnimationValue(view.animation_value.value) slideshowInterval = interval.toInt() slideshowIncludeVideos = view.include_videos.isChecked slideshowIncludeGIFs = view.include_gifs.isChecked slideshowRandomOrder = view.random_order.isChecked - slideshowUseFade = view.use_fade.isChecked slideshowMoveBackwards = view.move_backwards.isChecked loopSlideshow = view.loop_slideshow.isChecked } } + + private fun getAnimationText(): String { + return when (activity.config.slideshowAnimation) { + SLIDESHOW_ANIMATION_SLIDE -> activity.getString(R.string.slide) + SLIDESHOW_ANIMATION_FADE -> activity.getString(R.string.fade) + else -> activity.getString(R.string.no_animation) + } + } + + private fun getAnimationValue(text: String): Int { + return when (text) { + activity.getString(R.string.slide) -> SLIDESHOW_ANIMATION_SLIDE + activity.getString(R.string.fade) -> SLIDESHOW_ANIMATION_FADE + else -> SLIDESHOW_ANIMATION_NONE + } + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt index 3a5803d45..d47dda614 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt @@ -7,6 +7,8 @@ import android.content.Intent import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Matrix +import android.graphics.drawable.Drawable +import android.graphics.drawable.LayerDrawable import android.media.ExifInterface import android.os.Build import android.provider.MediaStore @@ -14,6 +16,9 @@ import android.util.DisplayMetrics import android.view.View import androidx.appcompat.app.AppCompatActivity import com.bumptech.glide.Glide +import com.bumptech.glide.load.DecodeFormat +import com.bumptech.glide.load.engine.DiskCacheStrategy +import com.bumptech.glide.request.RequestOptions import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.extensions.* @@ -163,8 +168,7 @@ fun BaseSimpleActivity.removeNoMedia(path: String, callback: (() -> Unit)? = nul return } - tryDeleteFileDirItem(file.toFileDirItem(applicationContext), false, false) { - scanPathRecursively(file.parent) + tryDeleteFileDirItem(file.toFileDirItem(), false, false) { callback?.invoke() } } @@ -186,9 +190,9 @@ fun BaseSimpleActivity.toggleFileVisibility(oldPath: String, hide: Boolean, call val newPath = "$path/$filename" renameFile(oldPath, newPath) { callback?.invoke(newPath) - Thread { + ensureBackgroundThread { updateDBMediaPath(oldPath, newPath) - }.start() + } } } @@ -208,12 +212,12 @@ fun BaseSimpleActivity.tryDeleteFileDirItem(fileDirItem: FileDirItem, allowDelet callback: ((wasSuccess: Boolean) -> Unit)? = null) { deleteFile(fileDirItem, allowDeleteFolder) { if (deleteFromDatabase) { - Thread { + ensureBackgroundThread { deleteDBPath(galleryDB.MediumDao(), fileDirItem.path) runOnUiThread { callback?.invoke(it) } - }.start() + } } else { callback?.invoke(it) } @@ -221,15 +225,20 @@ fun BaseSimpleActivity.tryDeleteFileDirItem(fileDirItem: FileDirItem, allowDelet } fun BaseSimpleActivity.movePathsInRecycleBin(paths: ArrayList, mediumDao: MediumDao = galleryDB.MediumDao(), callback: ((wasSuccess: Boolean) -> Unit)?) { - Thread { + ensureBackgroundThread { var pathsCnt = paths.size paths.forEach { val file = File(it) val internalFile = File(recycleBinPath, it) + val lastModified = file.lastModified() try { if (file.copyRecursively(internalFile, true)) { mediumDao.updateDeleted("$RECYCLE_BIN$it", System.currentTimeMillis(), it) pathsCnt-- + + if (config.keepLastModified) { + internalFile.setLastModified(lastModified) + } } } catch (e: Exception) { showErrorToast(e) @@ -237,7 +246,7 @@ fun BaseSimpleActivity.movePathsInRecycleBin(paths: ArrayList, mediumDao } } callback?.invoke(pathsCnt == 0) - }.start() + } } fun BaseSimpleActivity.restoreRecycleBinPath(path: String, callback: () -> Unit) { @@ -245,22 +254,27 @@ fun BaseSimpleActivity.restoreRecycleBinPath(path: String, callback: () -> Unit) } fun BaseSimpleActivity.restoreRecycleBinPaths(paths: ArrayList, mediumDao: MediumDao = galleryDB.MediumDao(), callback: () -> Unit) { - Thread { + ensureBackgroundThread { val newPaths = ArrayList() paths.forEach { val source = it val destination = it.removePrefix(recycleBinPath) + val lastModified = File(source).lastModified() var inputStream: InputStream? = null var out: OutputStream? = null try { out = getFileOutputStreamSync(destination, source.getMimeType()) - inputStream = getFileInputStreamSync(source)!! + inputStream = getFileInputStreamSync(source) inputStream.copyTo(out!!) if (File(source).length() == File(destination).length()) { mediumDao.updateDeleted(destination.removePrefix(recycleBinPath), 0, "$RECYCLE_BIN$destination") } newPaths.add(destination) + + if (config.keepLastModified) { + File(destination).setLastModified(lastModified) + } } catch (e: Exception) { showErrorToast(e) } finally { @@ -273,27 +287,31 @@ fun BaseSimpleActivity.restoreRecycleBinPaths(paths: ArrayList, mediumDa callback() } - fixDateTaken(newPaths) - }.start() + fixDateTaken(newPaths, false) + } } fun BaseSimpleActivity.emptyTheRecycleBin(callback: (() -> Unit)? = null) { - Thread { - recycleBin.deleteRecursively() - galleryDB.MediumDao().clearRecycleBin() - galleryDB.DirectoryDao().deleteRecycleBin() - toast(R.string.recycle_bin_emptied) - callback?.invoke() - }.start() + ensureBackgroundThread { + try { + recycleBin.deleteRecursively() + galleryDB.MediumDao().clearRecycleBin() + galleryDB.DirectoryDao().deleteRecycleBin() + toast(R.string.recycle_bin_emptied) + callback?.invoke() + } catch (e: Exception) { + toast(R.string.unknown_error_occurred) + } + } } fun BaseSimpleActivity.emptyAndDisableTheRecycleBin(callback: () -> Unit) { - Thread { + ensureBackgroundThread { emptyTheRecycleBin { config.useRecycleBin = false callback() } - }.start() + } } fun BaseSimpleActivity.showRecycleBinEmptyingDialog(callback: () -> Unit) { @@ -303,12 +321,12 @@ fun BaseSimpleActivity.showRecycleBinEmptyingDialog(callback: () -> Unit) { } fun BaseSimpleActivity.updateFavoritePaths(fileDirItems: ArrayList, destination: String) { - Thread { + ensureBackgroundThread { fileDirItems.forEach { val newPath = "$destination/${it.name}" updateDBMediaPath(it.path, newPath) } - }.start() + } } fun Activity.hasNavBar(): Boolean { @@ -323,9 +341,12 @@ fun Activity.hasNavBar(): Boolean { return (realDisplayMetrics.widthPixels - displayMetrics.widthPixels > 0) || (realDisplayMetrics.heightPixels - displayMetrics.heightPixels > 0) } -fun Activity.fixDateTaken(paths: ArrayList, callback: (() -> Unit)? = null) { +fun Activity.fixDateTaken(paths: ArrayList, showToasts: Boolean, callback: (() -> Unit)? = null) { val BATCH_SIZE = 50 - toast(R.string.fixing) + if (showToasts) { + toast(R.string.fixing) + } + try { var didUpdateFile = false val operations = ArrayList() @@ -366,13 +387,18 @@ fun Activity.fixDateTaken(paths: ArrayList, callback: (() -> Unit)? = nu didUpdateFile = false } - toast(if (didUpdateFile) R.string.dates_fixed_successfully else R.string.unknown_error_occurred) runOnUiThread { + if (showToasts) { + toast(if (didUpdateFile) R.string.dates_fixed_successfully else R.string.unknown_error_occurred) + } + callback?.invoke() } } } catch (e: Exception) { - showErrorToast(e) + if (showToasts) { + showErrorToast(e) + } } } @@ -409,12 +435,8 @@ fun BaseSimpleActivity.saveRotatedImageToFile(oldPath: String, newPath: String, saveFile(tmpPath, bitmap, it as FileOutputStream, newDegrees) } - if (File(newPath).exists()) { - tryDeleteFileDirItem(FileDirItem(newPath, newPath.getFilenameFromPath()), false, true) - } - copyFile(tmpPath, newPath) - scanPathRecursively(newPath) + rescanPaths(arrayListOf(newPath)) fileRotatedSuccessfully(newPath, oldLastModified) it.flush() @@ -478,7 +500,7 @@ fun BaseSimpleActivity.copyFile(source: String, destination: String) { try { out = getFileOutputStreamSync(destination, source.getMimeType()) inputStream = getFileInputStreamSync(source) - inputStream?.copyTo(out!!) + inputStream.copyTo(out!!) } finally { inputStream?.close() out?.close() @@ -491,3 +513,30 @@ fun saveFile(path: String, bitmap: Bitmap, out: FileOutputStream, degrees: Int) val bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) bmp.compress(path.getCompressionFormat(), 90, out) } + +fun Activity.getShortcutImage(tmb: String, drawable: Drawable, callback: () -> Unit) { + ensureBackgroundThread { + val options = RequestOptions() + .format(DecodeFormat.PREFER_ARGB_8888) + .skipMemoryCache(true) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .fitCenter() + + val size = resources.getDimension(R.dimen.shortcut_size).toInt() + val builder = Glide.with(this) + .asDrawable() + .load(tmb) + .apply(options) + .centerCrop() + .into(size, size) + + try { + (drawable as LayerDrawable).setDrawableByLayerId(R.id.shortcut_image, builder.get()) + } catch (e: Exception) { + } + + runOnUiThread { + callback() + } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt index 6560e9912..ea4b13734 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Context.kt @@ -13,6 +13,7 @@ import android.provider.MediaStore import android.view.WindowManager import android.widget.ImageView import com.bumptech.glide.Glide +import com.bumptech.glide.Priority import com.bumptech.glide.load.DecodeFormat import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions @@ -27,6 +28,7 @@ import com.simplemobiletools.gallery.pro.helpers.* import com.simplemobiletools.gallery.pro.interfaces.DirectoryDao import com.simplemobiletools.gallery.pro.interfaces.MediumDao import com.simplemobiletools.gallery.pro.interfaces.WidgetsDao +import com.simplemobiletools.gallery.pro.models.AlbumCover import com.simplemobiletools.gallery.pro.models.Directory import com.simplemobiletools.gallery.pro.models.Medium import com.simplemobiletools.gallery.pro.models.ThumbnailItem @@ -165,7 +167,20 @@ fun Context.getSortedDirectories(source: ArrayList): ArrayList AlphanumericComparator().compare(o1.name.toLowerCase(), o2.name.toLowerCase()) + sorting and SORT_BY_NAME != 0 -> { + if (sorting and SORT_USE_NUMERIC_VALUE != 0) { + AlphanumericComparator().compare(o1.name.toLowerCase(), o2.name.toLowerCase()) + } else { + o1.name.toLowerCase().compareTo(o2.name.toLowerCase()) + } + } + sorting and SORT_BY_PATH != 0 -> { + if (sorting and SORT_USE_NUMERIC_VALUE != 0) { + AlphanumericComparator().compare(o1.path.toLowerCase(), o2.path.toLowerCase()) + } else { + o1.path.toLowerCase().compareTo(o2.path.toLowerCase()) + } + } sorting and SORT_BY_PATH != 0 -> AlphanumericComparator().compare(o1.path.toLowerCase(), o2.path.toLowerCase()) sorting and SORT_BY_SIZE != 0 -> o1.size.compareTo(o2.size) sorting and SORT_BY_DATE_MODIFIED != 0 -> o1.modified.compareTo(o2.modified) @@ -200,7 +215,7 @@ fun Context.getDirsToShow(dirs: ArrayList, allDirs: ArrayList, allDirs: ArrayList, currentPathPrefix: String): ArrayList { val folders = dirs.map { it.path }.sorted().toMutableSet() as HashSet - val internalPath = internalStoragePath - val sdPath = sdCardPath val currentPaths = LinkedHashSet() + val foldersWithoutMediaFiles = ArrayList() + var newDirId = 1000L - folders.forEach { - val path = it - if (path != RECYCLE_BIN && path != FAVORITES && !path.equals(internalPath, true) && !path.equals(sdPath, true)) { - if (currentPathPrefix.isNotEmpty()) { - if (path == currentPathPrefix || File(path).parent.equals(currentPathPrefix, true)) { - currentPaths.add(path) - } - } else if (folders.any { !it.equals(path, true) && (File(path).parent.equals(it, true) || File(it).parent.equals(File(path).parent, true)) }) { - // if we have folders like - // /storage/emulated/0/Pictures/Images and - // /storage/emulated/0/Pictures/Screenshots, - // but /storage/emulated/0/Pictures is empty, show Images and Screenshots as separate folders, do not group them at /Pictures - val parent = File(path).parent - if (folders.contains(parent)) { - currentPaths.add(parent) - } else { - currentPaths.add(path) - } - } else { - currentPaths.add(path) + for (path in folders) { + if (path == RECYCLE_BIN || path == FAVORITES) { + continue + } + + if (currentPathPrefix.isNotEmpty()) { + if (!path.startsWith(currentPathPrefix, true)) { + continue } + + if (!File(path).parent.equals(currentPathPrefix, true)) { + continue + } + } + + if (currentPathPrefix.isNotEmpty() && path == currentPathPrefix || File(path).parent.equals(currentPathPrefix, true)) { + currentPaths.add(path) + } else if (folders.any { !it.equals(path, true) && (File(path).parent.equals(it, true) || File(it).parent.equals(File(path).parent, true)) }) { + // if we have folders like + // /storage/emulated/0/Pictures/Images and + // /storage/emulated/0/Pictures/Screenshots, + // but /storage/emulated/0/Pictures is empty, still Pictures with the first folders thumbnails and proper other info + val parent = File(path).parent + if (!folders.contains(parent) && dirs.none { it.path == parent }) { + currentPaths.add(parent) + val isSortingAscending = config.sorting and SORT_DESCENDING == 0 + val subDirs = dirs.filter { File(it.path).parent.equals(File(path).parent, true) } as ArrayList + if (subDirs.isNotEmpty()) { + val lastModified = if (isSortingAscending) { + subDirs.minBy { it.modified }?.modified + } else { + subDirs.maxBy { it.modified }?.modified + } ?: 0 + + val dateTaken = if (isSortingAscending) { + subDirs.minBy { it.taken }?.taken + } else { + subDirs.maxBy { it.taken }?.taken + } ?: 0 + + var mediaTypes = 0 + subDirs.forEach { + mediaTypes = mediaTypes or it.types + } + + val directory = Directory(newDirId++, + parent, + subDirs.first().tmb, + getFolderNameFromPath(parent), + subDirs.sumBy { it.mediaCnt }, + lastModified, + dateTaken, + subDirs.sumByLong { it.size }, + getPathLocation(parent), + mediaTypes) + + directory.containsMediaFilesDirectly = false + dirs.add(directory) + currentPaths.add(parent) + foldersWithoutMediaFiles.add(parent) + } + } + } else { + currentPaths.add(path) } } @@ -241,7 +299,7 @@ fun Context.getDirectParentSubfolders(dirs: ArrayList, currentPathPre currentPaths.forEach { val path = it currentPaths.forEach { - if (!it.equals(path) && File(it).parent?.equals(path) == true) { + if (!foldersWithoutMediaFiles.contains(it) && !it.equals(path, true) && File(it).parent?.equals(path, true) == true) { areDirectSubfoldersAvailable = true } } @@ -287,7 +345,10 @@ fun Context.updateSubfolderCounts(children: ArrayList, parentDirs: Ar // make sure we count only the proper direct subfolders, grouped the same way as on the main screen parentDirs.firstOrNull { it.path == longestSharedPath }?.apply { if (path.equals(child.path, true) || path.equals(File(child.path).parent, true) || children.any { it.path.equals(File(child.path).parent, true) }) { - subfoldersCount++ + if (child.containsMediaFilesDirectly) { + subfoldersCount++ + } + if (path != child.path) { subfoldersMediaCount += child.mediaCnt } @@ -297,7 +358,7 @@ fun Context.updateSubfolderCounts(children: ArrayList, parentDirs: Ar } fun Context.getNoMediaFolders(callback: (folders: ArrayList) -> Unit) { - Thread { + ensureBackgroundThread { val folders = ArrayList() val uri = MediaStore.Files.getContentUri("external") @@ -323,20 +384,20 @@ fun Context.getNoMediaFolders(callback: (folders: ArrayList) -> Unit) { } callback(folders) - }.start() + } } fun Context.rescanFolderMedia(path: String) { - Thread { + ensureBackgroundThread { rescanFolderMediaSync(path) - }.start() + } } fun Context.rescanFolderMediaSync(path: String) { getCachedMedia(path) { val cached = it GetMediaAsynctask(applicationContext, path, false, false, false) { - Thread { + ensureBackgroundThread { val newMedia = it val mediumDao = galleryDB.MediumDao() val media = newMedia.filter { it is Medium } as ArrayList @@ -350,15 +411,15 @@ fun Context.rescanFolderMediaSync(path: String) { } } } - }.start() + } }.execute() } } fun Context.storeDirectoryItems(items: ArrayList, directoryDao: DirectoryDao) { - Thread { + ensureBackgroundThread { directoryDao.insertAll(items) - }.start() + } } fun Context.checkAppendingHidden(path: String, hidden: String, includedFolders: MutableSet): String { @@ -412,14 +473,16 @@ fun Context.loadImage(type: Int, path: String, target: MySquareImageView, horizo } fun Context.addTempFolderIfNeeded(dirs: ArrayList): ArrayList { - val directories = ArrayList() val tempFolderPath = config.tempFolderPath - if (tempFolderPath.isNotEmpty()) { + return if (tempFolderPath.isNotEmpty()) { + val directories = ArrayList() val newFolder = Directory(null, tempFolderPath, "", tempFolderPath.getFilenameFromPath(), 0, 0, 0, 0L, getPathLocation(tempFolderPath), 0) directories.add(newFolder) + directories.addAll(dirs) + directories + } else { + dirs } - directories.addAll(dirs) - return directories } fun Context.getPathLocation(path: String): Int { @@ -435,6 +498,7 @@ fun Context.loadPng(path: String, target: MySquareImageView, cropThumbnails: Boo .signature(path.getFileSignature()) .skipMemoryCache(skipMemoryCacheAtPaths?.contains(path) == true) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .priority(Priority.LOW) .format(DecodeFormat.PREFER_ARGB_8888) val builder = Glide.with(applicationContext) @@ -449,6 +513,7 @@ fun Context.loadJpg(path: String, target: MySquareImageView, cropThumbnails: Boo val options = RequestOptions() .signature(path.getFileSignature()) .skipMemoryCache(skipMemoryCacheAtPaths?.contains(path) == true) + .priority(Priority.LOW) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) val builder = Glide.with(applicationContext) @@ -474,7 +539,7 @@ fun Context.loadSVG(path: String, target: MySquareImageView, cropThumbnails: Boo } fun Context.getCachedDirectories(getVideosOnly: Boolean = false, getImagesOnly: Boolean = false, directoryDao: DirectoryDao = galleryDB.DirectoryDao(), forceShowHidden: Boolean = false, callback: (ArrayList) -> Unit) { - Thread { + ensureBackgroundThread { val directories = try { directoryDao.getAll() as ArrayList } catch (e: Exception) { @@ -516,12 +581,12 @@ fun Context.getCachedDirectories(getVideosOnly: Boolean = false, getImagesOnly: callback(clone.distinctBy { it.path.getDistinctPath() } as ArrayList) removeInvalidDBDirectories(filteredDirectories, directoryDao) - }.start() + } } fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImagesOnly: Boolean = false, mediumDao: MediumDao = galleryDB.MediumDao(), callback: (ArrayList) -> Unit) { - Thread { + ensureBackgroundThread { val mediaFetcher = MediaFetcher(this) val foldersToScan = if (path.isEmpty()) mediaFetcher.getFoldersToScan() else arrayListOf(path) var media = ArrayList() @@ -579,7 +644,7 @@ fun Context.getCachedMedia(path: String, getVideosOnly: Boolean = false, getImag } } catch (ignored: Exception) { } - }.start() + } } fun Context.removeInvalidDBDirectories(dirs: ArrayList? = null, directoryDao: DirectoryDao = galleryDB.DirectoryDao()) { @@ -599,7 +664,10 @@ fun Context.updateDBMediaPath(oldPath: String, newPath: String) { } fun Context.updateDBDirectory(directory: Directory, directoryDao: DirectoryDao) { - directoryDao.updateDirectory(directory.path, directory.tmb, directory.mediaCnt, directory.modified, directory.taken, directory.size, directory.types) + try { + directoryDao.updateDirectory(directory.path, directory.tmb, directory.mediaCnt, directory.modified, directory.taken, directory.size, directory.types) + } catch (ignored: Exception) { + } } fun Context.getFavoritePaths(): ArrayList { @@ -673,7 +741,7 @@ fun Context.parseFileChannel(path: String, fc: FileChannel, level: Int, start: L val sb = StringBuilder() val buffer = ByteArray(1024) - while (true) { + while (sb.length < size) { val n = fis.read(buffer) if (n != -1) { sb.append(String(buffer, 0, n)) @@ -700,9 +768,9 @@ fun Context.parseFileChannel(path: String, fc: FileChannel, level: Int, start: L } fun Context.addPathToDB(path: String) { - Thread { + ensureBackgroundThread { if (!File(path).exists()) { - return@Thread + return@ensureBackgroundThread } val type = when { @@ -713,12 +781,51 @@ fun Context.addPathToDB(path: String) { else -> TYPE_IMAGES } - val videoDuration = if (type == TYPE_VIDEOS) path.getVideoDuration() else 0 - val medium = Medium(null, path.getFilenameFromPath(), path, path.getParentPath(), System.currentTimeMillis(), System.currentTimeMillis(), - File(path).length(), type, videoDuration, false, 0L) try { - galleryDB.MediumDao().insert(medium) + val mediumDao = galleryDB.MediumDao() + val isFavorite = mediumDao.isFavorite(path) + val videoDuration = if (type == TYPE_VIDEOS) path.getVideoDuration() else 0 + val medium = Medium(null, path.getFilenameFromPath(), path, path.getParentPath(), System.currentTimeMillis(), System.currentTimeMillis(), + File(path).length(), type, videoDuration, isFavorite, 0L) + + mediumDao.insert(medium) } catch (ignored: Exception) { } - }.start() + } +} + +fun Context.createDirectoryFromMedia(path: String, curMedia: ArrayList, albumCovers: ArrayList, hiddenString: String, + includedFolders: MutableSet, isSortingAscending: Boolean, getProperFileSize: Boolean): Directory { + var thumbnail = curMedia.firstOrNull { File(it.path).exists() }?.path ?: "" + albumCovers.forEach { + if (it.path == path && File(it.tmb).exists()) { + thumbnail = it.tmb + } + } + + val defaultMedium = Medium(0, "", "", "", 0L, 0L, 0L, 0, 0, false, 0L) + val firstItem = curMedia.firstOrNull() ?: defaultMedium + val lastItem = curMedia.lastOrNull() ?: defaultMedium + val dirName = checkAppendingHidden(path, hiddenString, includedFolders) + val lastModified = if (isSortingAscending) Math.min(firstItem.modified, lastItem.modified) else Math.max(firstItem.modified, lastItem.modified) + val dateTaken = if (isSortingAscending) Math.min(firstItem.taken, lastItem.taken) else Math.max(firstItem.taken, lastItem.taken) + val size = if (getProperFileSize) curMedia.sumByLong { it.size } else 0L + val mediaTypes = curMedia.getDirMediaTypes() + return Directory(null, path, thumbnail, dirName, curMedia.size, lastModified, dateTaken, size, getPathLocation(path), mediaTypes) +} + +fun Context.updateDirectoryPath(path: String) { + val mediaFetcher = MediaFetcher(applicationContext) + val getImagesOnly = false + val getVideosOnly = false + val hiddenString = getString(R.string.hidden) + val albumCovers = config.parseAlbumCovers() + val includedFolders = config.includedFolders + val isSortingAscending = config.directorySorting and SORT_DESCENDING == 0 + val getProperDateTaken = config.directorySorting and SORT_BY_DATE_TAKEN != 0 + val getProperFileSize = config.directorySorting and SORT_BY_SIZE != 0 + val favoritePaths = getFavoritePaths() + val curMedia = mediaFetcher.getFilesFrom(path, getImagesOnly, getVideosOnly, getProperDateTaken, getProperFileSize, favoritePaths, false) + val directory = createDirectoryFromMedia(path, curMedia, albumCovers, hiddenString, includedFolders, isSortingAscending, getProperFileSize) + updateDBDirectory(directory, galleryDB.DirectoryDao()) } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/String.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/String.kt index e07e80657..17710e0e7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/String.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/String.kt @@ -1,18 +1,10 @@ package com.simplemobiletools.gallery.pro.extensions import android.media.MediaMetadataRetriever -import com.bumptech.glide.signature.ObjectKey import com.simplemobiletools.gallery.pro.helpers.NOMEDIA import java.io.File import java.io.IOException -fun String.getFileSignature() = ObjectKey(getFileKey()) - -fun String.getFileKey(): String { - val file = File(this) - return "${file.absolutePath}${file.lastModified()}" -} - fun String.isThisOrParentIncluded(includedPaths: MutableSet) = includedPaths.any { startsWith(it, true) } fun String.isThisOrParentExcluded(excludedPaths: MutableSet) = excludedPaths.any { startsWith(it, true) } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt index e93d46050..fc80387e9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/PhotoFragment.kt @@ -21,6 +21,7 @@ import android.view.ViewGroup import com.alexvasilkov.gestures.GestureController import com.alexvasilkov.gestures.State import com.bumptech.glide.Glide +import com.bumptech.glide.Priority import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.DecodeFormat import com.bumptech.glide.load.engine.DiskCacheStrategy @@ -35,14 +36,12 @@ import com.davemorrissey.labs.subscaleview.ImageRegionDecoder import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.activities.PanoramaPhotoActivity import com.simplemobiletools.gallery.pro.activities.PhotoActivity import com.simplemobiletools.gallery.pro.extensions.* -import com.simplemobiletools.gallery.pro.helpers.MEDIUM -import com.simplemobiletools.gallery.pro.helpers.PATH -import com.simplemobiletools.gallery.pro.helpers.PicassoDecoder -import com.simplemobiletools.gallery.pro.helpers.PicassoRegionDecoder +import com.simplemobiletools.gallery.pro.helpers.* import com.simplemobiletools.gallery.pro.models.Medium import com.simplemobiletools.gallery.pro.svg.SvgSoftwareLayerSetter import com.squareup.picasso.Callback @@ -89,7 +88,14 @@ class PhotoFragment : ViewPagerFragment() { private lateinit var mMedium: Medium override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - mView = (inflater.inflate(R.layout.pager_photo_item, container, false) as ViewGroup).apply { + mView = (inflater.inflate(R.layout.pager_photo_item, container, false) as ViewGroup) + if (!arguments!!.getBoolean(SHOULD_INIT_FRAGMENT, true)) { + return mView + } + + mMedium = arguments!!.getSerializable(MEDIUM) as Medium + + mView.apply { subsampling_view.setOnClickListener { photoClicked() } gestures_view.setOnClickListener { photoClicked() } gif_view.setOnClickListener { photoClicked() } @@ -146,7 +152,6 @@ class PhotoFragment : ViewPagerFragment() { mIsFragmentVisible = true } - mMedium = arguments!!.getSerializable(MEDIUM) as Medium if (mMedium.path.startsWith("content://") && !mMedium.path.startsWith("content://mms/")) { val originalPath = mMedium.path mMedium.path = context!!.getRealPathFromURI(Uri.parse(originalPath)) ?: mMedium.path @@ -226,20 +231,31 @@ class PhotoFragment : ViewPagerFragment() { super.onDestroyView() if (activity?.isDestroyed == false) { mView.subsampling_view.recycle() + + try { + if (context != null) { + Glide.with(context!!).clear(mView.gestures_view) + } + } catch (ignored: Exception) { + } } mLoadZoomableViewHandler.removeCallbacksAndMessages(null) if (mCurrentRotationDegrees != 0) { - Thread { + ensureBackgroundThread { val path = mMedium.path (activity as? BaseSimpleActivity)?.saveRotatedImageToFile(path, path, mCurrentRotationDegrees, false) {} - }.start() + } } } override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) + if (!mWasInit) { + return + } + // avoid GIFs being skewed, played in wrong aspect ratio if (mMedium.isGIF()) { mView.onGlobalLayout { @@ -359,9 +375,11 @@ class PhotoFragment : ViewPagerFragment() { } private fun loadBitmap(addZoomableView: Boolean = true) { + val priority = if (mIsFragmentVisible) Priority.IMMEDIATE else Priority.NORMAL val options = RequestOptions() .signature(mMedium.path.getFileSignature()) .format(DecodeFormat.PREFER_ARGB_8888) + .priority(priority) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) .fitCenter() @@ -540,7 +558,7 @@ class PhotoFragment : ViewPagerFragment() { tag?.getValueAsInt(defaultOrientation) ?: defaultOrientation } else { val exif = android.media.ExifInterface(path) - exif.getAttributeInt(android.media.ExifInterface.TAG_ORIENTATION, defaultOrientation) + exif.getAttributeInt(TAG_ORIENTATION, defaultOrientation) } if (orient == defaultOrientation || context!!.isPathOnOTG(mMedium.path)) { @@ -641,6 +659,7 @@ class PhotoFragment : ViewPagerFragment() { if (mIsPanorama) { panorama_outline.animate().alpha(if (isFullscreen) 0f else 1f).start() + panorama_outline.isClickable = !isFullscreen } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt index 8bf276b80..1f14eef95 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/VideoFragment.kt @@ -24,14 +24,12 @@ import com.google.android.exoplayer2.upstream.DataSource import com.google.android.exoplayer2.upstream.DataSpec import com.google.android.exoplayer2.upstream.FileDataSource import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.activities.PanoramaVideoActivity import com.simplemobiletools.gallery.pro.activities.VideoActivity import com.simplemobiletools.gallery.pro.extensions.* -import com.simplemobiletools.gallery.pro.helpers.Config -import com.simplemobiletools.gallery.pro.helpers.MEDIUM -import com.simplemobiletools.gallery.pro.helpers.MIN_SKIP_LENGTH -import com.simplemobiletools.gallery.pro.helpers.PATH +import com.simplemobiletools.gallery.pro.helpers.* import com.simplemobiletools.gallery.pro.models.Medium import com.simplemobiletools.gallery.pro.views.MediaSideScroll import kotlinx.android.synthetic.main.bottom_video_time_holder.view.* @@ -77,6 +75,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S private lateinit var mSeekBar: SeekBar override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + mMedium = arguments!!.getSerializable(MEDIUM) as Medium mConfig = context!!.config mView = inflater.inflate(R.layout.pager_video_item, container, false).apply { instant_prev_item.setOnClickListener { listener?.goToPrevItem() } @@ -125,8 +124,11 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S } } + if (!arguments!!.getBoolean(SHOULD_INIT_FRAGMENT, true)) { + return mView + } + storeStateVariables() - mMedium = arguments!!.getSerializable(MEDIUM) as Medium Glide.with(context!!).load(mMedium.path).into(mView.video_preview) // setMenuVisibility is not called at VideoActivity (third party intent) @@ -138,9 +140,11 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S initTimeHolder() checkIfPanorama() - activity?.getVideoResolution(mMedium.path)?.apply { - mVideoSize.x = x - mVideoSize.y = y + ensureBackgroundThread { + activity?.getVideoResolution(mMedium.path)?.apply { + mVideoSize.x = x + mVideoSize.y = y + } } if (mIsPanorama) { @@ -654,10 +658,10 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S private fun releaseExoPlayer() { mExoPlayer?.stop() - Thread { + ensureBackgroundThread { mExoPlayer?.release() mExoPlayer = null - }.start() + } } override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {} @@ -667,9 +671,9 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?) = false override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) { - Thread { + ensureBackgroundThread { mExoPlayer?.setVideoSurface(Surface(mTextureView.surfaceTexture)) - }.start() + } } private fun setVideoSize() { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Config.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Config.kt index 3f0c9839e..45642f914 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Config.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Config.kt @@ -203,7 +203,7 @@ class Config(context: Context) : BaseConfig(context) { set(blackBackground) = prefs.edit().putBoolean(BLACK_BACKGROUND, blackBackground).apply() var filterMedia: Int - get() = prefs.getInt(FILTER_MEDIA, TYPE_IMAGES or TYPE_VIDEOS or TYPE_GIFS or TYPE_RAWS or TYPE_SVGS) + get() = prefs.getInt(FILTER_MEDIA, TYPE_DEFAULT_FILTER) set(filterMedia) = prefs.edit().putInt(FILTER_MEDIA, filterMedia).apply() var dirColumnCnt: Int @@ -303,14 +303,14 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getBoolean(SLIDESHOW_RANDOM_ORDER, false) set(slideshowRandomOrder) = prefs.edit().putBoolean(SLIDESHOW_RANDOM_ORDER, slideshowRandomOrder).apply() - var slideshowUseFade: Boolean - get() = prefs.getBoolean(SLIDESHOW_USE_FADE, false) - set(slideshowUseFade) = prefs.edit().putBoolean(SLIDESHOW_USE_FADE, slideshowUseFade).apply() - var slideshowMoveBackwards: Boolean get() = prefs.getBoolean(SLIDESHOW_MOVE_BACKWARDS, false) set(slideshowMoveBackwards) = prefs.edit().putBoolean(SLIDESHOW_MOVE_BACKWARDS, slideshowMoveBackwards).apply() + var slideshowAnimation: Int + get() = prefs.getInt(SLIDESHOW_ANIMATION, SLIDESHOW_ANIMATION_SLIDE) + set(slideshowAnimation) = prefs.edit().putInt(SLIDESHOW_ANIMATION, slideshowAnimation).apply() + var loopSlideshow: Boolean get() = prefs.getBoolean(SLIDESHOW_LOOP, false) set(loopSlideshow) = prefs.edit().putBoolean(SLIDESHOW_LOOP, loopSlideshow).apply() @@ -387,8 +387,8 @@ class Config(context: Context) : BaseConfig(context) { fun getLastVideoPosition(path: String) = prefs.getInt("$LAST_VIDEO_POSITION_PREFIX${path.toLowerCase()}", 0) - fun getAllLastVideoPositions() = prefs.all.filterKeys { - it.startsWith(LAST_VIDEO_POSITION_PREFIX) + fun getAllLastVideoPositions() = prefs.all.filterKeys { + it.startsWith(LAST_VIDEO_POSITION_PREFIX) } var rememberLastVideoPosition: Boolean diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Constants.kt index e3af08f5c..015c12beb 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/Constants.kt @@ -84,13 +84,19 @@ const val SLIDESHOW_INTERVAL = "slideshow_interval" const val SLIDESHOW_INCLUDE_VIDEOS = "slideshow_include_videos" const val SLIDESHOW_INCLUDE_GIFS = "slideshow_include_gifs" const val SLIDESHOW_RANDOM_ORDER = "slideshow_random_order" -const val SLIDESHOW_USE_FADE = "slideshow_use_fade" const val SLIDESHOW_MOVE_BACKWARDS = "slideshow_move_backwards" +const val SLIDESHOW_ANIMATION = "slideshow_animation" const val SLIDESHOW_LOOP = "loop_slideshow" const val SLIDESHOW_DEFAULT_INTERVAL = 5 -const val SLIDESHOW_SCROLL_DURATION = 500L +const val SLIDESHOW_SLIDE_DURATION = 500L +const val SLIDESHOW_FADE_DURATION = 1500L const val SLIDESHOW_START_ON_ENTER = "slideshow_start_on_enter" +// slideshow animations +const val SLIDESHOW_ANIMATION_NONE = 0 +const val SLIDESHOW_ANIMATION_SLIDE = 1 +const val SLIDESHOW_ANIMATION_FADE = 2 + const val NOMEDIA = ".nomedia" const val FAVORITES = "favorites" const val RECYCLE_BIN = "recycle_bin" @@ -109,6 +115,7 @@ const val DRAG_THRESHOLD = 8 const val MONTH_MILLISECONDS = MONTH_SECONDS * 1000L const val MIN_SKIP_LENGTH = 2000 const val HIDE_SYSTEM_UI_DELAY = 500L +const val MAX_PRINT_SIDE_SIZE = 4096 const val DIRECTORY = "directory" const val MEDIUM = "medium" @@ -119,6 +126,7 @@ const val GET_ANY_INTENT = "get_any_intent" const val SET_WALLPAPER_INTENT = "set_wallpaper_intent" const val IS_VIEW_INTENT = "is_view_intent" const val PICKED_PATHS = "picked_paths" +const val SHOULD_INIT_FRAGMENT = "should_init_fragment" // rotations const val ROTATE_BY_SYSTEM_SETTING = 0 @@ -153,17 +161,20 @@ const val TYPE_VIDEOS = 2 const val TYPE_GIFS = 4 const val TYPE_RAWS = 8 const val TYPE_SVGS = 16 +const val TYPE_DEFAULT_FILTER = TYPE_IMAGES or TYPE_VIDEOS or TYPE_GIFS or TYPE_RAWS or TYPE_SVGS const val LOCATION_INTERNAL = 1 const val LOCATION_SD = 2 const val LOCATION_OTG = 3 const val GROUP_BY_NONE = 1 -const val GROUP_BY_LAST_MODIFIED = 2 -const val GROUP_BY_DATE_TAKEN = 4 +const val GROUP_BY_LAST_MODIFIED_DAILY = 2 +const val GROUP_BY_DATE_TAKEN_DAILY = 4 const val GROUP_BY_FILE_TYPE = 8 const val GROUP_BY_EXTENSION = 16 const val GROUP_BY_FOLDER = 32 +const val GROUP_BY_LAST_MODIFIED_MONTHLY = 64 +const val GROUP_BY_DATE_TAKEN_MONTHLY = 128 const val GROUP_DESCENDING = 1024 // bottom actions diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/DefaultPageTransformer.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/DefaultPageTransformer.kt new file mode 100644 index 000000000..95981ba4a --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/DefaultPageTransformer.kt @@ -0,0 +1,8 @@ +package com.simplemobiletools.gallery.pro.helpers + +import android.view.View +import androidx.viewpager.widget.ViewPager + +class DefaultPageTransformer : ViewPager.PageTransformer { + override fun transformPage(view: View, position: Float) {} +} diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/FadePageTransformer.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/FadePageTransformer.kt new file mode 100644 index 000000000..3ed113b40 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/FadePageTransformer.kt @@ -0,0 +1,18 @@ +package com.simplemobiletools.gallery.pro.helpers + +import android.view.View +import androidx.viewpager.widget.ViewPager + +class FadePageTransformer : ViewPager.PageTransformer { + override fun transformPage(view: View, position: Float) { + view.translationX = view.width * -position + + view.alpha = if (position <= -1f || position >= 1f) { + 0f + } else if (position == 0f) { + 1f + } else { + 1f - Math.abs(position) + } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/MediaFetcher.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/MediaFetcher.kt index 785627944..a67a88468 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/MediaFetcher.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/MediaFetcher.kt @@ -126,7 +126,7 @@ class MediaFetcher(val context: Context) { if (cursor.moveToFirst()) { do { val path = cursor.getStringValue(MediaStore.Images.Media.DATA) - val parentPath = File(path).parent?.trimEnd('/') ?: continue + val parentPath = File(path).parent ?: continue if (!includedFolders.contains(parentPath) && !foldersToIgnore.contains(parentPath)) { foldersToScan.add(parentPath) } @@ -287,8 +287,20 @@ class MediaFetcher(val context: Context) { o1 as Medium o2 as Medium var result = when { - sorting and SORT_BY_NAME != 0 -> AlphanumericComparator().compare(o1.name.toLowerCase(), o2.name.toLowerCase()) - sorting and SORT_BY_PATH != 0 -> AlphanumericComparator().compare(o1.path.toLowerCase(), o2.path.toLowerCase()) + sorting and SORT_BY_NAME != 0 -> { + if (sorting and SORT_USE_NUMERIC_VALUE != 0) { + AlphanumericComparator().compare(o1.name.toLowerCase(), o2.name.toLowerCase()) + } else { + o1.name.toLowerCase().compareTo(o2.name.toLowerCase()) + } + } + sorting and SORT_BY_PATH != 0 -> { + if (sorting and SORT_USE_NUMERIC_VALUE != 0) { + AlphanumericComparator().compare(o1.path.toLowerCase(), o2.path.toLowerCase()) + } else { + o1.path.toLowerCase().compareTo(o2.path.toLowerCase()) + } + } sorting and SORT_BY_SIZE != 0 -> o1.size.compareTo(o2.size) sorting and SORT_BY_DATE_MODIFIED != 0 -> o1.modified.compareTo(o2.modified) else -> o1.taken.compareTo(o2.taken) @@ -324,7 +336,8 @@ class MediaFetcher(val context: Context) { } val sortDescending = currentGrouping and GROUP_DESCENDING != 0 - val sorted = if (currentGrouping and GROUP_BY_DATE_TAKEN != 0 || currentGrouping and GROUP_BY_LAST_MODIFIED != 0) { + val sorted = if (currentGrouping and GROUP_BY_LAST_MODIFIED_DAILY != 0 || currentGrouping and GROUP_BY_LAST_MODIFIED_MONTHLY != 0 || + currentGrouping and GROUP_BY_DATE_TAKEN_DAILY != 0 || currentGrouping and GROUP_BY_DATE_TAKEN_MONTHLY != 0) { mediumGroups.toSortedMap(if (sortDescending) compareByDescending { it.toLongOrNull() ?: 0L } else { @@ -339,8 +352,8 @@ class MediaFetcher(val context: Context) { mediumGroups[key] = value } - val today = formatDate(System.currentTimeMillis().toString()) - val yesterday = formatDate((System.currentTimeMillis() - DAY_SECONDS * 1000).toString()) + val today = formatDate(System.currentTimeMillis().toString(), true) + val yesterday = formatDate((System.currentTimeMillis() - DAY_SECONDS * 1000).toString(), true) for ((key, value) in mediumGroups) { val sectionKey = getFormattedKey(key, currentGrouping, today, yesterday) thumbnailItems.add(ThumbnailSection(sectionKey)) @@ -351,13 +364,20 @@ class MediaFetcher(val context: Context) { } private fun getFormattedKey(key: String, grouping: Int, today: String, yesterday: String): String { - return when { - grouping and GROUP_BY_LAST_MODIFIED != 0 || grouping and GROUP_BY_DATE_TAKEN != 0 -> getFinalDate(formatDate(key), today, yesterday) + var result = when { + grouping and GROUP_BY_LAST_MODIFIED_DAILY != 0 || grouping and GROUP_BY_DATE_TAKEN_DAILY != 0 -> getFinalDate(formatDate(key, true), today, yesterday) + grouping and GROUP_BY_LAST_MODIFIED_MONTHLY != 0 || grouping and GROUP_BY_DATE_TAKEN_MONTHLY != 0 -> formatDate(key, false) grouping and GROUP_BY_FILE_TYPE != 0 -> getFileTypeString(key) grouping and GROUP_BY_EXTENSION != 0 -> key.toUpperCase() grouping and GROUP_BY_FOLDER != 0 -> context.humanizePath(key) else -> key } + + if (result.isEmpty()) { + result = context.getString(R.string.unknown) + } + + return result } private fun getFinalDate(date: String, today: String, yesterday: String): String { @@ -368,11 +388,12 @@ class MediaFetcher(val context: Context) { } } - private fun formatDate(timestamp: String): String { + private fun formatDate(timestamp: String, showDay: Boolean): String { return if (timestamp.areDigitsOnly()) { val cal = Calendar.getInstance(Locale.ENGLISH) cal.timeInMillis = timestamp.toLong() - DateFormat.format("dd MMM yyyy", cal).toString() + val format = if (showDay) "dd MMM yyyy" else "MMM yyyy" + DateFormat.format(format, cal).toString() } else { "" } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/MyWidgetProvider.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/MyWidgetProvider.kt index 2af024791..5ba0e3811 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/MyWidgetProvider.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/helpers/MyWidgetProvider.kt @@ -10,12 +10,17 @@ import android.widget.RemoteViews import com.bumptech.glide.Glide import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.request.RequestOptions +import com.simplemobiletools.commons.extensions.getFileSignature import com.simplemobiletools.commons.extensions.setBackgroundColor import com.simplemobiletools.commons.extensions.setText import com.simplemobiletools.commons.extensions.setVisibleIf +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.activities.MediaActivity -import com.simplemobiletools.gallery.pro.extensions.* +import com.simplemobiletools.gallery.pro.extensions.config +import com.simplemobiletools.gallery.pro.extensions.directoryDB +import com.simplemobiletools.gallery.pro.extensions.getFolderNameFromPath +import com.simplemobiletools.gallery.pro.extensions.widgetsDB import com.simplemobiletools.gallery.pro.models.Widget class MyWidgetProvider : AppWidgetProvider() { @@ -30,7 +35,7 @@ class MyWidgetProvider : AppWidgetProvider() { override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { super.onUpdate(context, appWidgetManager, appWidgetIds) - Thread { + ensureBackgroundThread { val config = context.config context.widgetsDB.getWidgets().filter { appWidgetIds.contains(it.widgetId) }.forEach { val views = RemoteViews(context.packageName, R.layout.widget).apply { @@ -44,7 +49,12 @@ class MyWidgetProvider : AppWidgetProvider() { val options = RequestOptions() .signature(path.getFileSignature()) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - if (context.config.cropThumbnails) options.centerCrop() else options.fitCenter() + + if (context.config.cropThumbnails) { + options.centerCrop() + } else { + options.fitCenter() + } val density = context.resources.displayMetrics.density val appWidgetOptions = appWidgetManager.getAppWidgetOptions(appWidgetIds.first()) @@ -66,7 +76,7 @@ class MyWidgetProvider : AppWidgetProvider() { setupAppOpenIntent(context, views, R.id.widget_holder, it) appWidgetManager.updateAppWidget(it.widgetId, views) } - }.start() + } } override fun onAppWidgetOptionsChanged(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int, newOptions: Bundle) { @@ -76,10 +86,10 @@ class MyWidgetProvider : AppWidgetProvider() { override fun onDeleted(context: Context, appWidgetIds: IntArray) { super.onDeleted(context, appWidgetIds) - Thread { + ensureBackgroundThread { appWidgetIds.forEach { context.widgetsDB.deleteWidgetId(it) } - }.start() + } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/interfaces/MediumDao.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/interfaces/MediumDao.kt index 1ce2bb641..490bd62f4 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/interfaces/MediumDao.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/interfaces/MediumDao.kt @@ -21,6 +21,9 @@ interface MediumDao { @Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, video_duration, is_favorite, deleted_ts FROM media WHERE deleted_ts != 0") fun getDeletedMedia(): List + @Query("SELECT is_favorite FROM media WHERE full_path = :path COLLATE NOCASE") + fun isFavorite(path: String): Boolean + @Insert(onConflict = REPLACE) fun insert(medium: Medium) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/jobs/NewPhotoFetcher.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/jobs/NewPhotoFetcher.kt index 8039ae280..e00e2eb4f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/jobs/NewPhotoFetcher.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/jobs/NewPhotoFetcher.kt @@ -12,8 +12,11 @@ import android.net.Uri import android.os.Build import android.os.Handler import android.provider.MediaStore +import com.simplemobiletools.commons.extensions.getParentPath import com.simplemobiletools.commons.extensions.getStringValue +import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.gallery.pro.extensions.addPathToDB +import com.simplemobiletools.gallery.pro.extensions.updateDirectoryPath // based on https://developer.android.com/reference/android/app/job/JobInfo.Builder.html#addTriggerContentUri(android.app.job.JobInfo.TriggerContentUri) @TargetApi(Build.VERSION_CODES.N) @@ -54,6 +57,7 @@ class NewPhotoFetcher : JobService() { override fun onStartJob(params: JobParameters): Boolean { mRunningParams = params + val affectedFolderPaths = HashSet() if (params.triggeredContentAuthorities != null && params.triggeredContentUris != null) { val ids = arrayListOf() for (uri in params.triggeredContentUris!!) { @@ -80,6 +84,7 @@ class NewPhotoFetcher : JobService() { cursor = contentResolver.query(it, projection, selection.toString(), null, null) while (cursor!!.moveToNext()) { val path = cursor!!.getStringValue(MediaStore.Images.ImageColumns.DATA) + affectedFolderPaths.add(path.getParentPath()) addPathToDB(path) } } @@ -90,6 +95,12 @@ class NewPhotoFetcher : JobService() { } } + ensureBackgroundThread { + affectedFolderPaths.forEach { + updateDirectoryPath(it) + } + } + mHandler.post(mWorker) return true } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Directory.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Directory.kt index f74af2abc..3b2ebedc5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Directory.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Directory.kt @@ -26,7 +26,8 @@ data class Directory( // used with "Group direct subfolders" enabled @Ignore var subfoldersCount: Int = 0, - @Ignore var subfoldersMediaCount: Int = 0) { + @Ignore var subfoldersMediaCount: Int = 0, + @Ignore var containsMediaFilesDirectly: Boolean = true) { constructor() : this(null, "", "", "", 0, 0L, 0L, 0L, 0, 0, 0, 0) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Medium.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Medium.kt index 4851de9b0..6044219d7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Medium.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/Medium.kt @@ -56,8 +56,10 @@ data class Medium( fun getGroupingKey(groupBy: Int): String { return when { - groupBy and GROUP_BY_LAST_MODIFIED != 0 -> getDayStartTS(modified) - groupBy and GROUP_BY_DATE_TAKEN != 0 -> getDayStartTS(taken) + groupBy and GROUP_BY_LAST_MODIFIED_DAILY != 0 -> getDayStartTS(modified, false) + groupBy and GROUP_BY_LAST_MODIFIED_MONTHLY != 0 -> getDayStartTS(modified, true) + groupBy and GROUP_BY_DATE_TAKEN_DAILY != 0 -> getDayStartTS(taken, false) + groupBy and GROUP_BY_DATE_TAKEN_MONTHLY != 0 -> getDayStartTS(taken, true) groupBy and GROUP_BY_FILE_TYPE != 0 -> type.toString() groupBy and GROUP_BY_EXTENSION != 0 -> name.getFilenameExtension().toLowerCase() groupBy and GROUP_BY_FOLDER != 0 -> parentPath @@ -67,13 +69,17 @@ data class Medium( fun getIsInRecycleBin() = deletedTS != 0L - private fun getDayStartTS(ts: Long): String { + private fun getDayStartTS(ts: Long, resetDays: Boolean): String { val calendar = Calendar.getInstance(Locale.ENGLISH).apply { timeInMillis = ts set(Calendar.HOUR_OF_DAY, 0) set(Calendar.MINUTE, 0) set(Calendar.SECOND, 0) set(Calendar.MILLISECOND, 0) + + if (resetDays) { + set(Calendar.DAY_OF_MONTH, 1) + } } return calendar.timeInMillis.toString() diff --git a/app/src/main/res/drawable/shortcut_image.xml b/app/src/main/res/drawable/shortcut_image.xml new file mode 100644 index 000000000..20dde1a45 --- /dev/null +++ b/app/src/main/res/drawable/shortcut_image.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 84912ef58..bbf53b09e 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -48,9 +48,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" android:paddingStart="@dimen/normal_margin" - android:paddingLeft="@dimen/normal_margin" android:visibility="gone"> @@ -62,7 +60,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentStart="true" - android:layout_alignParentLeft="true" android:layout_alignParentBottom="true" android:paddingTop="@dimen/normal_margin" android:visibility="gone"> diff --git a/app/src/main/res/layout/activity_media.xml b/app/src/main/res/layout/activity_media.xml index 222ca5826..852cec099 100644 --- a/app/src/main/res/layout/activity_media.xml +++ b/app/src/main/res/layout/activity_media.xml @@ -48,9 +48,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" android:paddingStart="@dimen/normal_margin" - android:paddingLeft="@dimen/normal_margin" android:visibility="gone"> @@ -62,7 +60,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentStart="true" - android:layout_alignParentLeft="true" android:layout_alignParentBottom="true" android:paddingTop="@dimen/normal_margin" android:visibility="gone"> diff --git a/app/src/main/res/layout/activity_panorama_photo.xml b/app/src/main/res/layout/activity_panorama_photo.xml index 199fb8d8f..0a4cd3f99 100644 --- a/app/src/main/res/layout/activity_panorama_photo.xml +++ b/app/src/main/res/layout/activity_panorama_photo.xml @@ -23,7 +23,7 @@ android:id="@+id/cardboard" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" android:layout_alignParentBottom="true" android:padding="@dimen/activity_margin" android:src="@drawable/ic_cardboard"/> @@ -32,7 +32,7 @@ android:id="@+id/explore" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_alignParentBottom="true" android:padding="@dimen/activity_margin" android:src="@drawable/ic_explore"/> diff --git a/app/src/main/res/layout/activity_panorama_video.xml b/app/src/main/res/layout/activity_panorama_video.xml index 343496d24..45e5fb637 100644 --- a/app/src/main/res/layout/activity_panorama_video.xml +++ b/app/src/main/res/layout/activity_panorama_video.xml @@ -17,7 +17,7 @@ android:id="@+id/explore" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_alignParentBottom="true" android:padding="@dimen/activity_margin" android:src="@drawable/ic_explore"/> @@ -26,7 +26,7 @@ android:id="@+id/cardboard" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" android:layout_alignParentBottom="true" android:padding="@dimen/activity_margin" android:src="@drawable/ic_cardboard"/> diff --git a/app/src/main/res/layout/activity_search.xml b/app/src/main/res/layout/activity_search.xml new file mode 100644 index 000000000..13f9fb57e --- /dev/null +++ b/app/src/main/res/layout/activity_search.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index c0f1c51a9..4a8c5a1c1 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -2,6 +2,7 @@ @@ -29,7 +30,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/customize_colors"/> @@ -52,7 +52,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/use_english_language" app:switchPadding="@dimen/medium_margin"/> @@ -75,7 +74,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/change_date_and_time_format"/> @@ -97,7 +95,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toStartOf="@+id/settings_file_loading_priority" - android:layout_toLeftOf="@+id/settings_file_loading_priority" android:paddingLeft="@dimen/medium_margin" android:paddingRight="@dimen/medium_margin" android:text="@string/file_loading_priority"/> @@ -107,11 +104,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" android:layout_marginEnd="@dimen/small_margin" - android:layout_marginRight="@dimen/small_margin" android:background="@null" - android:clickable="false"/> + android:clickable="false" + tools:text="@string/compromise"/> @@ -127,7 +123,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/visibility" android:textAllCaps="true" @@ -150,7 +145,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/manage_included_folders"/> @@ -172,7 +166,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/manage_excluded_folders"/> @@ -194,7 +187,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/manage_hidden_folders"/> @@ -217,7 +209,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/show_hidden_items" app:switchPadding="@dimen/medium_margin"/> @@ -235,7 +226,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/videos" android:textAllCaps="true" @@ -259,7 +249,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/autoplay_videos" app:switchPadding="@dimen/medium_margin"/> @@ -283,7 +272,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/remember_last_video_position" app:switchPadding="@dimen/medium_margin"/> @@ -307,7 +295,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/loop_videos" app:switchPadding="@dimen/medium_margin"/> @@ -331,7 +318,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/open_videos_on_separate_screen" app:switchPadding="@dimen/medium_margin"/> @@ -355,7 +341,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/allow_video_gestures" app:switchPadding="@dimen/medium_margin"/> @@ -373,7 +358,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/thumbnails" android:textAllCaps="true" @@ -397,7 +381,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/animate_gifs" app:switchPadding="@dimen/medium_margin"/> @@ -421,7 +404,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/crop_thumbnails" app:switchPadding="@dimen/medium_margin"/> @@ -445,7 +427,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/show_thumbnail_video_duration" app:switchPadding="@dimen/medium_margin"/> @@ -469,7 +450,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/show_media_count" app:switchPadding="@dimen/medium_margin"/> @@ -487,7 +467,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/scrolling" android:textAllCaps="true" @@ -511,7 +490,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/show_info_bubble" app:switchPadding="@dimen/medium_margin"/> @@ -535,7 +513,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/scroll_thumbnails_horizontally" app:switchPadding="@dimen/medium_margin"/> @@ -559,7 +536,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/enable_pull_to_refresh" app:switchPadding="@dimen/medium_margin"/> @@ -577,7 +553,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/fullscreen_media" android:textAllCaps="true" @@ -601,7 +576,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/max_brightness" app:switchPadding="@dimen/medium_margin"/> @@ -625,7 +599,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/black_background_at_fullscreen" app:switchPadding="@dimen/medium_margin"/> @@ -649,7 +622,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/hide_system_ui_at_fullscreen" app:switchPadding="@dimen/medium_margin"/> @@ -673,7 +645,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/allow_instant_change" app:switchPadding="@dimen/medium_margin"/> @@ -697,7 +668,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/allow_photo_gestures" app:switchPadding="@dimen/medium_margin"/> @@ -721,7 +691,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/allow_down_gesture" app:switchPadding="@dimen/medium_margin"/> @@ -745,7 +714,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/show_notch" app:switchPadding="@dimen/medium_margin"/> @@ -768,7 +736,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toStartOf="@+id/settings_screen_rotation" - android:layout_toLeftOf="@+id/settings_screen_rotation" android:paddingLeft="@dimen/medium_margin" android:paddingRight="@dimen/medium_margin" android:text="@string/screen_rotation_by"/> @@ -778,9 +745,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" android:layout_marginEnd="@dimen/small_margin" - android:layout_marginRight="@dimen/small_margin" android:background="@null" android:clickable="false"/> @@ -798,7 +763,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/deep_zoomable_images" android:textAllCaps="true" @@ -822,7 +786,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/allow_deep_zooming_images" app:switchPadding="@dimen/medium_margin"/> @@ -846,7 +809,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/allow_rotating_gestures" app:switchPadding="@dimen/medium_margin"/> @@ -870,7 +832,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/show_highest_quality" app:switchPadding="@dimen/medium_margin"/> @@ -894,7 +855,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/allow_one_to_one_zoom" app:switchPadding="@dimen/medium_margin"/> @@ -912,7 +872,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/extended_details" android:textAllCaps="true" @@ -936,7 +895,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/show_extended_details" app:switchPadding="@dimen/medium_margin"/> @@ -959,7 +917,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/hide_extended_details" app:switchPadding="@dimen/medium_margin"/> @@ -981,7 +938,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/manage_extended_details"/> @@ -998,7 +954,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/security" android:textAllCaps="true" @@ -1022,7 +977,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/password_protect_hidden_items" app:switchPadding="@dimen/medium_margin"/> @@ -1046,7 +1000,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/password_protect_whole_app" app:switchPadding="@dimen/medium_margin"/> @@ -1070,7 +1023,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/password_protect_file_deletion" app:switchPadding="@dimen/medium_margin"/> @@ -1088,7 +1040,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/file_operations" android:textAllCaps="true" @@ -1112,7 +1063,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/delete_empty_folders" app:switchPadding="@dimen/medium_margin"/> @@ -1136,7 +1086,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/keep_last_modified" app:switchPadding="@dimen/medium_margin"/> @@ -1160,7 +1109,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/skip_delete_confirmation" app:switchPadding="@dimen/medium_margin"/> @@ -1178,7 +1126,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/bottom_actions" android:textAllCaps="true" @@ -1202,7 +1149,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/show_at_bottom" app:switchPadding="@dimen/medium_margin"/> @@ -1225,7 +1171,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/manage_bottom_actions"/> @@ -1242,7 +1187,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/recycle_bin" android:textAllCaps="true" @@ -1266,7 +1210,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/move_items_into_recycle_bin" app:switchPadding="@dimen/medium_margin"/> @@ -1290,7 +1233,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/show_recycle_bin" app:switchPadding="@dimen/medium_margin"/> @@ -1314,7 +1256,6 @@ android:background="@null" android:clickable="false" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/show_recycle_bin_last" app:switchPadding="@dimen/medium_margin"/> @@ -1337,7 +1278,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toStartOf="@+id/settings_empty_recycle_bin_size" - android:layout_toLeftOf="@+id/settings_empty_recycle_bin_size" android:paddingLeft="@dimen/medium_margin" android:paddingRight="@dimen/medium_margin" android:text="@string/empty_recycle_bin"/> @@ -1347,9 +1287,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" android:layout_marginEnd="@dimen/small_margin" - android:layout_marginRight="@dimen/small_margin" android:background="@null" android:clickable="false"/> @@ -1367,7 +1305,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/bigger_margin" - android:layout_marginLeft="@dimen/bigger_margin" android:layout_marginTop="@dimen/activity_margin" android:text="@string/migrating" android:textAllCaps="true" @@ -1390,7 +1327,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/export_settings"/> @@ -1412,7 +1348,6 @@ android:layout_height="wrap_content" android:layout_centerVertical="true" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:text="@string/import_settings"/> diff --git a/app/src/main/res/layout/activity_video_player.xml b/app/src/main/res/layout/activity_video_player.xml index d7962a628..224c6425a 100644 --- a/app/src/main/res/layout/activity_video_player.xml +++ b/app/src/main/res/layout/activity_video_player.xml @@ -23,8 +23,7 @@ android:id="@+id/video_volume_controller" android:layout_width="@dimen/media_side_slider_width" android:layout_height="match_parent" - android:layout_alignParentEnd="true" - android:layout_alignParentRight="true"/> + android:layout_alignParentEnd="true"/> @@ -100,7 +100,6 @@ android:layout_alignTop="@+id/config_bg_color" android:layout_alignBottom="@+id/config_bg_color" android:layout_toEndOf="@+id/config_bg_color" - android:layout_toRightOf="@+id/config_bg_color" android:background="@android:color/white"> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_favorite" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_edit" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_share" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_delete" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_rotate" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_properties" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_change_orientation" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_slideshow" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_show_on_map" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_toggle_file_visibility" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_rename" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_set_as" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_copy" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> diff --git a/app/src/main/res/layout/bottom_actions_aspect_ratio.xml b/app/src/main/res/layout/bottom_actions_aspect_ratio.xml index 8663bf358..e5ffd02df 100644 --- a/app/src/main/res/layout/bottom_actions_aspect_ratio.xml +++ b/app/src/main/res/layout/bottom_actions_aspect_ratio.xml @@ -17,9 +17,12 @@ android:textAllCaps="true" android:textColor="@android:color/white" android:textSize="@dimen/big_text_size" + app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/bottom_aspect_ratio_one_one" app:layout_constraintHorizontal_bias="0.5" - app:layout_constraintStart_toStartOf="parent"/> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_aspect_ratio_free" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_aspect_ratio_one_one" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_aspect_ratio_four_three" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> + app:layout_constraintStart_toEndOf="@+id/bottom_aspect_ratio_sixteen_nine" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.0"/> diff --git a/app/src/main/res/layout/bottom_editor_draw_actions.xml b/app/src/main/res/layout/bottom_editor_draw_actions.xml index fb12e40b2..8026820e2 100644 --- a/app/src/main/res/layout/bottom_editor_draw_actions.xml +++ b/app/src/main/res/layout/bottom_editor_draw_actions.xml @@ -24,7 +24,7 @@ android:id="@+id/bottom_draw_color_clickable" android:layout_width="@dimen/bottom_editor_color_picker_size" android:layout_height="@dimen/bottom_editor_color_picker_size" - android:layout_marginRight="@dimen/small_margin" + android:layout_marginEnd="@dimen/small_margin" android:background="?attr/selectableItemBackgroundBorderless" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintRight_toLeftOf="@+id/bottom_draw_undo" @@ -34,7 +34,7 @@ android:id="@+id/bottom_draw_color" android:layout_width="@dimen/bottom_editor_color_picker_size" android:layout_height="@dimen/bottom_editor_color_picker_size" - android:layout_marginRight="@dimen/small_margin" + android:layout_marginEnd="@dimen/small_margin" android:clickable="false" android:padding="@dimen/small_margin" android:src="@drawable/circle_background" @@ -46,7 +46,7 @@ android:id="@+id/bottom_draw_undo" android:layout_width="@dimen/bottom_editor_color_picker_size" android:layout_height="@dimen/bottom_editor_color_picker_size" - android:layout_marginRight="@dimen/normal_margin" + android:layout_marginEnd="@dimen/normal_margin" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="false" android:padding="@dimen/medium_margin" diff --git a/app/src/main/res/layout/bottom_video_time_holder.xml b/app/src/main/res/layout/bottom_video_time_holder.xml index ec34b6501..53701119c 100644 --- a/app/src/main/res/layout/bottom_video_time_holder.xml +++ b/app/src/main/res/layout/bottom_video_time_holder.xml @@ -50,7 +50,6 @@ android:layout_alignTop="@+id/video_seekbar" android:layout_alignBottom="@+id/video_seekbar" android:layout_alignParentStart="true" - android:layout_alignParentLeft="true" android:background="?attr/selectableItemBackgroundBorderless" android:gravity="center_vertical" android:paddingLeft="@dimen/activity_margin" @@ -64,9 +63,7 @@ android:layout_height="wrap_content" android:layout_below="@+id/video_toggle_play_pause" android:layout_toStartOf="@+id/video_duration" - android:layout_toLeftOf="@+id/video_duration" android:layout_toEndOf="@+id/video_curr_time" - android:layout_toRightOf="@+id/video_curr_time" android:paddingTop="@dimen/activity_margin" android:paddingBottom="@dimen/activity_margin"/> @@ -78,7 +75,6 @@ android:layout_alignTop="@+id/video_seekbar" android:layout_alignBottom="@+id/video_seekbar" android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" android:background="?attr/selectableItemBackgroundBorderless" android:gravity="center_vertical" android:paddingLeft="@dimen/activity_margin" diff --git a/app/src/main/res/layout/dialog_change_grouping.xml b/app/src/main/res/layout/dialog_change_grouping.xml index a51c19111..c64aad625 100644 --- a/app/src/main/res/layout/dialog_change_grouping.xml +++ b/app/src/main/res/layout/dialog_change_grouping.xml @@ -29,20 +29,36 @@ android:text="@string/do_not_group_files"/> + android:text="@string/by_last_modified_daily"/> + android:text="@string/by_last_modified_monthly"/> + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_custom_aspect_ratio.xml b/app/src/main/res/layout/dialog_custom_aspect_ratio.xml index 3f9180ae0..7650ee275 100644 --- a/app/src/main/res/layout/dialog_custom_aspect_ratio.xml +++ b/app/src/main/res/layout/dialog_custom_aspect_ratio.xml @@ -33,8 +33,8 @@ android:layout_height="wrap_content" android:layout_alignTop="@+id/aspect_ratio_width" android:layout_alignBottom="@+id/aspect_ratio_width" - android:layout_toLeftOf="@+id/aspect_ratio_height" - android:layout_toRightOf="@+id/aspect_ratio_width" + android:layout_toStartOf="@+id/aspect_ratio_height" + android:layout_toEndOf="@+id/aspect_ratio_width" android:gravity="center" android:text=":" android:textStyle="bold"/> @@ -44,8 +44,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="50dp" - android:layout_marginLeft="50dp" - android:layout_toRightOf="@+id/aspect_ratio_width_label" + android:layout_toEndOf="@+id/aspect_ratio_width_label" android:text="@string/height"/> + android:paddingStart="@dimen/normal_margin"> @@ -40,7 +36,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentStart="true" - android:layout_alignParentLeft="true" android:layout_alignParentBottom="true" android:paddingTop="@dimen/normal_margin"> diff --git a/app/src/main/res/layout/dialog_medium_picker.xml b/app/src/main/res/layout/dialog_medium_picker.xml index c9b59d2d8..cc06575dc 100644 --- a/app/src/main/res/layout/dialog_medium_picker.xml +++ b/app/src/main/res/layout/dialog_medium_picker.xml @@ -19,9 +19,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" - android:paddingStart="@dimen/normal_margin" - android:paddingLeft="@dimen/normal_margin"> + android:paddingStart="@dimen/normal_margin"> @@ -32,7 +30,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentStart="true" - android:layout_alignParentLeft="true" android:layout_alignParentBottom="true" android:paddingTop="@dimen/normal_margin"> diff --git a/app/src/main/res/layout/dialog_other_aspect_ratio.xml b/app/src/main/res/layout/dialog_other_aspect_ratio.xml index 61487c688..661245a51 100644 --- a/app/src/main/res/layout/dialog_other_aspect_ratio.xml +++ b/app/src/main/res/layout/dialog_other_aspect_ratio.xml @@ -27,7 +27,7 @@ android:id="@+id/other_aspect_ratio_2_1" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingLeft="@dimen/small_margin" + android:paddingStart="@dimen/small_margin" android:paddingTop="@dimen/normal_margin" android:paddingBottom="@dimen/normal_margin" android:text="2:1" @@ -37,18 +37,17 @@ android:id="@+id/other_aspect_ratio_3_2" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingLeft="@dimen/small_margin" + android:paddingStart="@dimen/small_margin" android:paddingTop="@dimen/normal_margin" android:paddingBottom="@dimen/normal_margin" android:text="3:2" android:textSize="@dimen/bigger_text_size"/> - + android:paddingEnd="@dimen/small_margin"/> @@ -17,7 +18,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:paddingTop="@dimen/activity_margin" android:paddingBottom="@dimen/activity_margin" android:text="@string/interval"/> @@ -27,23 +27,53 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" android:ems="5" - android:gravity="right" + android:gravity="end" android:imeOptions="actionDone" android:inputType="number" - android:maxLength="2" + android:maxLength="5" android:textCursorDrawable="@null" android:textSize="@dimen/normal_text_size"/> + + + + + + + + @@ -64,7 +94,6 @@ android:layout_below="@+id/include_videos_holder" android:background="?attr/selectableItemBackground" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:paddingTop="@dimen/activity_margin" android:paddingBottom="@dimen/activity_margin"> @@ -85,7 +114,6 @@ android:layout_below="@+id/include_gifs_holder" android:background="?attr/selectableItemBackground" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:paddingTop="@dimen/activity_margin" android:paddingBottom="@dimen/activity_margin"> @@ -100,35 +128,12 @@ - - - - - - @@ -149,7 +154,6 @@ android:layout_below="@+id/move_backwards_holder" android:background="?attr/selectableItemBackground" android:paddingStart="@dimen/medium_margin" - android:paddingLeft="@dimen/medium_margin" android:paddingTop="@dimen/activity_margin" android:paddingBottom="@dimen/activity_margin"> diff --git a/app/src/main/res/layout/directory_item_grid.xml b/app/src/main/res/layout/directory_item_grid.xml index 550001a4a..9f72281c9 100644 --- a/app/src/main/res/layout/directory_item_grid.xml +++ b/app/src/main/res/layout/directory_item_grid.xml @@ -17,10 +17,9 @@ android:id="@+id/dir_check" android:layout_width="@dimen/selection_check_size" android:layout_height="@dimen/selection_check_size" - android:layout_alignRight="@+id/dir_shadow_holder" + android:layout_alignEnd="@+id/dir_shadow_holder" android:layout_alignParentTop="true" android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" android:layout_margin="@dimen/small_margin" android:background="@drawable/circle_background" android:padding="@dimen/tiny_margin" @@ -32,7 +31,6 @@ android:layout_width="@dimen/selection_check_size" android:layout_height="@dimen/selection_check_size" android:layout_alignParentStart="true" - android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_margin="@dimen/small_margin" android:background="@drawable/circle_black_background" @@ -44,8 +42,8 @@ android:id="@+id/dir_shadow_holder" android:layout_width="match_parent" android:layout_height="@dimen/tmb_shadow_height" - android:layout_alignLeft="@+id/dir_bottom_holder" - android:layout_alignRight="@+id/dir_bottom_holder" + android:layout_alignStart="@+id/dir_bottom_holder" + android:layout_alignEnd="@+id/dir_bottom_holder" android:layout_alignParentBottom="true" android:background="@drawable/gradient_background"/> @@ -53,8 +51,8 @@ android:id="@+id/dir_bottom_holder" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_alignLeft="@+id/dir_thumbnail" - android:layout_alignRight="@+id/dir_thumbnail" + android:layout_alignStart="@+id/dir_thumbnail" + android:layout_alignEnd="@+id/dir_thumbnail" android:layout_alignParentBottom="true" android:gravity="bottom" android:orientation="vertical" @@ -69,9 +67,9 @@ android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="2" + android:paddingBottom="@dimen/small_margin" android:shadowColor="@color/default_background_color" android:shadowRadius="4" - android:paddingBottom="@dimen/small_margin" android:textColor="@android:color/white" android:textSize="@dimen/normal_text_size"/> @@ -88,11 +86,10 @@ android:id="@+id/dir_location" android:layout_width="@dimen/sd_card_icon_size" android:layout_height="@dimen/sd_card_icon_size" - android:layout_alignRight="@+id/dir_bottom_holder" + android:layout_alignEnd="@+id/dir_bottom_holder" android:layout_alignParentBottom="true" android:alpha="0.8" android:paddingEnd="@dimen/small_margin" - android:paddingRight="@dimen/small_margin" android:paddingBottom="@dimen/small_margin" android:src="@drawable/ic_sd_card" android:visibility="gone"/> diff --git a/app/src/main/res/layout/directory_item_list.xml b/app/src/main/res/layout/directory_item_list.xml index 4a0036d7f..8534c4552 100644 --- a/app/src/main/res/layout/directory_item_list.xml +++ b/app/src/main/res/layout/directory_item_list.xml @@ -6,7 +6,7 @@ android:layout_height="wrap_content" android:clickable="true" android:focusable="true" - android:paddingLeft="@dimen/small_margin" + android:paddingStart="@dimen/small_margin" android:paddingTop="@dimen/small_margin"> @@ -58,7 +57,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/dir_name" - android:layout_toRightOf="@+id/dir_name" + android:layout_toEndOf="@+id/dir_name" android:alpha="0.4" android:textColor="@android:color/white" android:textSize="@dimen/smaller_text_size"/> @@ -68,9 +67,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" android:layout_alignParentBottom="true" - android:layout_marginRight="@dimen/small_margin" + android:layout_marginEnd="@dimen/small_margin" android:gravity="end" android:orientation="horizontal" android:paddingBottom="@dimen/tiny_margin"> @@ -98,7 +96,7 @@ android:layout_height="1dp" android:layout_alignBottom="@+id/dir_thumbnail" android:layout_marginTop="2dp" - android:layout_toRightOf="@+id/dir_thumbnail" + android:layout_toEndOf="@+id/dir_thumbnail" android:background="@drawable/divider"/> diff --git a/app/src/main/res/layout/pager_photo_item.xml b/app/src/main/res/layout/pager_photo_item.xml index 7484532eb..2336176cb 100644 --- a/app/src/main/res/layout/pager_photo_item.xml +++ b/app/src/main/res/layout/pager_photo_item.xml @@ -45,7 +45,7 @@ android:id="@+id/photo_details" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_marginLeft="@dimen/small_margin" android:layout_marginRight="@dimen/small_margin" android:background="@color/gradient_grey_start" @@ -59,8 +59,7 @@ android:id="@+id/photo_brightness_controller" android:layout_width="@dimen/media_side_slider_width" android:layout_height="match_parent" - android:layout_alignParentStart="true" - android:layout_alignParentLeft="true"/> + android:layout_alignParentStart="true"/> + android:layout_alignParentEnd="true"/> diff --git a/app/src/main/res/layout/pager_video_item.xml b/app/src/main/res/layout/pager_video_item.xml index 9db21e6a4..4a18f5add 100644 --- a/app/src/main/res/layout/pager_video_item.xml +++ b/app/src/main/res/layout/pager_video_item.xml @@ -28,8 +28,7 @@ android:id="@+id/video_volume_controller" android:layout_width="@dimen/media_side_slider_width" android:layout_height="match_parent" - android:layout_alignParentEnd="true" - android:layout_alignParentRight="true"/> + android:layout_alignParentEnd="true"/> + android:layout_alignParentEnd="true"/> @@ -48,9 +47,9 @@ android:id="@+id/play_outline" android:layout_width="@dimen/play_outline_icon_size" android:layout_height="@dimen/play_outline_icon_size" - android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" android:layout_alignParentBottom="true" - android:layout_marginRight="@dimen/small_margin" + android:layout_marginEnd="@dimen/small_margin" android:paddingBottom="6dp" android:src="@drawable/img_play_outline_empty" android:visibility="gone"/> @@ -61,7 +60,7 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="6dp" - android:layout_toLeftOf="@+id/play_outline" + android:layout_toStartOf="@+id/play_outline" android:paddingLeft="@dimen/small_margin" android:paddingRight="@dimen/small_margin" android:paddingBottom="@dimen/small_margin" @@ -75,7 +74,7 @@ android:layout_height="1dp" android:layout_alignBottom="@+id/medium_thumbnail" android:layout_marginTop="2dp" - android:layout_toRightOf="@+id/medium_thumbnail" + android:layout_toEndOf="@+id/medium_thumbnail" android:background="@drawable/divider"/> diff --git a/app/src/main/res/menu/cab_directories.xml b/app/src/main/res/menu/cab_directories.xml index e2e19a58b..a7f29794a 100644 --- a/app/src/main/res/menu/cab_directories.xml +++ b/app/src/main/res/menu/cab_directories.xml @@ -48,19 +48,15 @@ android:id="@+id/cab_exclude" android:title="@string/exclude" app:showAsAction="never"/> - - + + + diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index 1de075c0c..0d9b32e12 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -5,8 +5,7 @@ android:id="@+id/search" android:icon="@drawable/ic_search" android:title="@string/search" - app:actionViewClass="androidx.appcompat.widget.SearchView" - app:showAsAction="collapseActionView|ifRoom"/> + app:showAsAction="always"/> + + + + diff --git a/app/src/main/res/menu/menu_viewpager.xml b/app/src/main/res/menu/menu_viewpager.xml index 282910e8a..ed3dcc8ac 100644 --- a/app/src/main/res/menu/menu_viewpager.xml +++ b/app/src/main/res/menu/menu_viewpager.xml @@ -110,6 +110,14 @@ android:icon="@drawable/ic_rename_new" android:title="@string/rename" app:showAsAction="ifRoom"/> + + إدارة المجلدات المضمنة اضافة مجلد إذا كان لديك بعض المجلدات التي تحتوي على الملتيميديا ، ولكن لم يتم التعرف عليها من قبل التطبيق، يمكنك إضافتها يدويا هنا.\n + No media files have been found. You can solve it by adding the folders containing media files manually. \n لن تؤدي إضافة بعض العناصر هنا إلى استبعاد أي مجلد آخر. @@ -116,12 +117,14 @@ تضمين الفديو تضمين GIF ترتيب عشوائي - استخدام تاثير التلاشي ارجع للخلف حلقة عرض الشرائح + Animation + None + Fade + Slide انتهى عرض الشرائح لم يتم العثور على وسائط لعرض الشرائح - Use crossfade animations تغيير طريقة العرض @@ -134,7 +137,11 @@ Do not group files Folder Last modified + Last modified (daily) + Last modified (monthly) Date taken + Date taken (daily) + Date taken (monthly) File type Extension Please note that grouping and sorting are 2 independent fields diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 046a14dba..d621f25e5 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -63,6 +63,7 @@ Manage included folders Add folder If you have some folders which contain media, but were not recognized by the app, you can add them manually here.\n\nAdding some items here will not exclude any other folder. + No media files have been found. You can solve it by adding the folders containing media files manually. Resize @@ -112,12 +113,14 @@ Include videos Include GIFs Random order - Use fade animations Move backwards Loop slideshow + Animation + None + Fade + Slide The slideshow ended No media for the slideshow have been found - Use crossfade animations Change view type @@ -130,7 +133,11 @@ Do not group files Folder Last modified + Last modified (daily) + Last modified (monthly) Date taken + Date taken (daily) + Date taken (monthly) File type Extension Please note that grouping and sorting are 2 independent fields diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 3d9c658ed..030f3a19a 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -32,7 +32,7 @@ Fixant… Data fixada correctament Comparteix una versió redimensionada - Hey,\n\nseems like you upgraded from the old free app. You can now uninstall the old version, which has an \'Upgrade to Pro\' button at the top of the app settings.\n\nYou will only have the Recycle bin items deleted, favorite items unmarked and you will also have to reset your app settings.\n\nThanks! + Hola,\n\nsembla que heu actualitzat des de l\'antiga aplicació gratuïta. Ara podeu desinstal·lar la versió antiga, que té un botó "Actualitza a Pro" a la part superior de la configuració de l’aplicació.\nNomés s’eliminaran els elements de la paperera, els elements preferits sense marcar i també caldrà restablirla configuració de la vostra aplicació.\n\nGràcies! Filtre d’arxius @@ -63,6 +63,7 @@ Gestionar carpetes incloses Agregar carpeta Si tens alguna carpeta que contingui multimèdia però no ha estat reconeguda per la aplicació, pots agregar-les manualment aquí. + No s’ha trobat cap fitxer multimèdia. Podeu resoldre-ho afegint manualment les carpetes que contenen fitxers multimèdia. Redimensionar @@ -112,12 +113,14 @@ Inclou vídeos Inclou GIFs Ordre aleatori - Utilitza animacions de desaparició Moure cap enrere Presentació de diapositives + Animació + Cap + Esvair + Lliscar S’ha acabat la presentació de diapositives No s’han trobat mitjans per a la presentació de diapositives - Utilitzeu animacions creuades Canviar el tipus de vista @@ -130,7 +133,11 @@ No agrupar fitxers Carpeta Darrer modificat + Darrer modificat (diari) + Darrer modificat (mensual) Data de presa + Data de presa (diari) + Data de presa (mensual) Tipus de fitxer Extensió Tingueu en compte que l’agrupació i la classificació són 2 camps independents @@ -216,12 +223,12 @@ Si, només heu d’utilitzar l’ítem del menú \"Agrupar per\" mentre es troba a la vista en miniatura. Podeu agrupar fitxers amb diversos criteris, inclòs data de presa. Si utilitzeu la funció \"Mostra el contingut de totes les carpetes\", també podeu agrupar-les per carpetes. L’ordenació per data que de presa no sembla funcionar correctament, com puc solucionar-ho? Probablement, els fitxers es copiïn en un lloc incorrecte. Podeu arreglar-ho si seleccioneu les miniatures del fitxer i seleccioneu \"Fixar data de presa\". - I see some color banding on the images. How can I improve the quality? - The current solution for displaying images works fine in the vast majority of cases, but if you want even better image quality, you can enable the \"Show images in the highest possible quality\" at the app settings, in the \"Deep zoomable images\" section. - I have hidden a file/folder. How can I unhide it? - You can either press the \"Temporarily show hidden items\" menu item at the main screen, or toggle \"Show hidden items\" in the app settings to see the hidden item. If you want to unhide it, just long press it and select \"Unhide\". Folders are hidden by adding a hidden \".nomedia\" file into them, you can delete the file with any file manager too. - Why does the app take up so much space? - App cache can take up to 250MB, it ensures quicker image loading. If the app is taking up even more space, it is most likely caused by you having items in the Recycle Bin. Those files count to the app size. You can clear the Recycle bin by opening it and deleting all files, or from the app settings. Every file in the Bin is deleted automatically after 30 days. + Veig algunes bandes de colors a les imatges. Com puc millorar la qualitat? + La solució actual per mostrar imatges funciona bé en la gran majoria dels casos, però si voleu obtenir una millor qualitat d\'imatge, podeu activar \"Mostra les imatges amb la màxima qualitat possible\" a la configuració de l’aplicació, a la secció \"Imatges ampliades a mida\". + He amagat un fitxer / carpeta. Com puc mostrar-la? + Podeu prémer l’element de menú \"Mostra temporalment elements ocults\" a la pantalla principal o canviar \"Mostra els elements ocults\" a la configuració de l’aplicació per veure l’element amagat. Si voleu mostrar-la sempre, premeu-la i seleccioneu \"Mostra\". Les carpetes s\'amaguen afegint un fitxer \".nomedia\" ocult en elles, també podeu eliminar el fitxer amb qualsevol gestor de fitxers. + Per què l’aplicació ocupa molt d’espai? + La memòria cau d’aplicacions pot ocupar fins a 250 MB, garanteix una càrrega de les imatges més ràpida. Si l’aplicació ocupa més espai, probablement sigui per tenir elements a la Paperera de reciclatge. Aquests fitxers compten a la mida de l’aplicació. Podeu esborrar la paperera de reciclatge obrint-la i suprimint tots els fitxers o des de la configuració de l’aplicació. Els fitxers de la paperera s’eliminen automàticament després de 30 dies. diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index c8d15c1e5..1ebb50c7c 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -63,6 +63,7 @@ Spravovat přidané složky Přidat složku Pokud máte nějaké složky obsahující média, ale nebyly aplikací nalezeny, můžete je zde přidat ručně. + No media files have been found. You can solve it by adding the folders containing media files manually. Změnit velikost @@ -112,12 +113,14 @@ Zahrnout videa Zahrnout GIFy Náhodné pořadí - Použít animaci slábnutí Jít opačným směrem Opakovat prezentaci ve smyčce + Animation + None + Fade + Slide Prezentace skončila Nebyla nalezena žádná média pro prezentaci - Použít animaci prolnutí Změnit typ zobrazení @@ -130,7 +133,11 @@ Neseskupovat soubory Složky Data poslední úpravy + Last modified (daily) + Last modified (monthly) Data pořízení + Date taken (daily) + Date taken (monthly) Typu souboru Přípony Mějte prosím na paměti, že seskupování a řazení jsou 2 nezávislé hodnoty diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 56124fb01..8985ded14 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -63,6 +63,7 @@ Administrer inkluderede mapper Tilføj mappe Hvis du har mapper med mediefiler som appen ikke har fundet, kan du manuelt tilføje dem her.\n\nDet vil ikke ekskludere andre mapper. + Ingen mediefiler er fundet. Dette kan løses ved manuelt at tilføje mapper som indeholder mediefiler. Skaler @@ -112,12 +113,14 @@ Inkluder videoer Inkluder GIF\'er Tilfældig rækkefølge - Brug udtonende animationer Kør baglæns Endeløs kørsel + Animation + Ingen + Udton + Glid Slideshowet endte Der blev ikke funket nogen mediefiler til slideshowet - Anvend crossfade-animationer Skift visning @@ -130,7 +133,11 @@ Gruppér ikke filer Mappe Sidst ændret + Sidst ændret (daglig) + Sidst ændret (månedlig) Eksponeringsdato + Eksponeringsdato (daglig) + Eksponeringsdato (månedlig) Filtype Filendelse Vær opmærksom på at gruppering og sortering er to individuelle felter diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 79ec823fa..f2e8d74bf 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -32,7 +32,7 @@ Korrigiere… Datum erfolgreich korrigiert. Teile eine verkleinerte Version - Hey,\n\nseems like you upgraded from the old free app. You can now uninstall the old version, which has an \'Upgrade to Pro\' button at the top of the app settings.\n\nYou will only have the Recycle bin items deleted, favorite items unmarked and you will also have to reset your app settings.\n\nThanks! + Hey,\n\nes sieht so aus, als hättest du von der alten kostenlosen App geupgraded. Du kannst nun die alte Version deinstallieren, die oben in den App-Einstellungen einen \'Upgrade auf Pro\' Button hat.\n\nEs wird nur der Papierkorb gelöscht, die Markierungen von Favoriten entfernt und die App-Einstellungen zurückgesetzt.\n\nDanke! Filter @@ -63,6 +63,7 @@ Einbezogene Ordner verwalten Ordner hinzufügen Solltest du weitere Mediendateien haben, die von der App nicht gefunden wurden, kannst du deren Ordner hier manuell hinzufügen. + No media files have been found. You can solve it by adding the folders containing media files manually. Größe ändern @@ -112,12 +113,14 @@ Videos verwenden GIFs verwenden Zufällige Reihenfolge - Übergänge animieren Rückwärts abspielen Endlos abspielen + Animation + None + Fade + Slide Diashow beendet. Keine Medien für Diashow gefunden. - Verwende Überblendanimationen Darstellung ändern @@ -130,7 +133,11 @@ Dateien nicht gruppieren Ordner Datum der letzten Änderung + Last modified (daily) + Last modified (monthly) Aufnahmedatum + Date taken (daily) + Date taken (monthly) Dateityp (Bilder/Videos) Dateierweiterung Bitte beachte, dass Gruppieren und Sortieren zwei unabhängige Felder sind. @@ -219,12 +226,12 @@ Die jetzige Methode für die Anzeige von Bildern funktioniert gut, aber für eine noch bessere Bildqualität kann die Einstellung \"Zeige Bilder in der höchstmöglichen Qualität\" im Menü unter \"Stark vergrösserbare Bilder\" gesetzt werden. Ich habe eine versteckte Datei bzw. einen versteckten Ordner. Wie kann ich diese/n sichtbar stellen? Du kannst entweder auf \"Verstecktes temporär anzeigen\" im Hauptmenü drücken oder die Einstellung \"Versteckte Elemente anzeigen\" setzen. Wenn du es sichtbar einstellen willst, drücke lange darauf und wähle \"Nicht verstecken\" aus. Ordner werden durch eine versteckte, in ihnen gespeicherte \".nomedia\"-Datei versteckt und das Löschen der Datei ist mit jedem Dateimanger möglich. - Why does the app take up so much space? - App cache can take up to 250MB, it ensures quicker image loading. If the app is taking up even more space, it is most likely caused by you having items in the Recycle Bin. Those files count to the app size. You can clear the Recycle bin by opening it and deleting all files, or from the app settings. Every file in the Bin is deleted automatically after 30 days. + Warum beansprucht die App so viel Speicherplatz? + Der Cache der App kann bis zu 250 MB groß werden und sorgt dafür, dass die Bilder schneller geladen werden. Wenn die App noch mehr Speicherplatz beansprucht, liegt das wahrscheinlich daran, dass der Papierkorb zu voll ist. Diese Dateien zählen zum Speicherplatz der App dazu. Du kannst den Papierkorb leeren, indem du ihn öffnest und alle Dateien darin löschst, oder den entsprechenden Button in den Einstellungen betätigst. All 30 Tage wird der Papierkorb automatisch geleert. - Simple Gallery Pro: Photo Manager & Editor + Schlichte Galerie Pro: Foto Manager & Editor Galerie ohne Werbung. Ordnen, Bearbeiten und Wiederherstellen von Fotos & Videos @@ -256,10 +263,10 @@ • Schlichte Galerie Pro ist Open Source … und viele, viele mehr! - FOTO EDITOR + FOTOEDITOR Schlichte Galerie Pro macht es schnell und einfach deine Bilder zu bearbeiten. Schneide Bilder zu, drehe sie und ändere die Größe. Wenn du dich etwas kreativer fühlst, kannst du Filter hinzufügen und auf deinen Bildern malen! - UNTERSTÜTZUNG FÜR VIELE DATEITYPEEN + UNTERSTÜTZUNG FÜR VIELE DATEITYPEN Im Gegensatz zu einigen anderen Galerien unterstütz Schlichte Galerie Pro eine Vielzahl verschiedener Dateitypen. Unter anderem JPEG, PNG, MP4, MKV, RAW, SVG, Panoramabilder, Panoramavideos und viele mehr. STARK INDIVIDUALISIERBARE GALERIE @@ -268,7 +275,7 @@ WIEDERHERSTELLUNG GELÖSCHTER FOTOS & VIDEOS Versehentlich ein wertvolles Foto oder Video gelöscht? Keine Sorge! Schlichte Galerie Pro verfügt über einen praktischen Papierkorb, aus dem du gelöschte Bilder & Videos leicht wiederherstellen kannst. - SCHÜTZE & VERSTECKE FOTOS, VIDEOS & DATEIEN + SCHÜTZE UND VERSTECKE FOTOS, VIDEOS & DATEIEN Mit einem PIN, Muster oder dem Fingerabdrucksensor deines Gerätes kannst du Fotos, Videos und komplette Alben verstecken und schützen. Du kannst auch die App selber schützen oder bestimmte Funktionen der App sperren. Beispielsweise kannst du eine Datei nicht ohne Scan des Fingerabdrucks löschen, um deine Dateien vor versehentlichem Löschen zu schützen. Schau dir die vollständige Serie der Schlichten Apps hier an: diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index eb6a51e51..cd2a4ef12 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -1,7 +1,7 @@ - Simple Gallery - Gallery + Απλή Συλλογή + Συλλογή Επεξεργασία Άνοιγμα κάμερας (κρυφά) @@ -49,9 +49,9 @@ Εξαίρεση Εξαίρεση φακέλων Διαχείριση εξαιρεμένων φακέλων - Αυτό θα εξαιρέσει το επιλεγμένο μαζί με τους υποφακέλους από το Simple Gallery μόνο. Μπορείτε να διαχειριστείτε τους φακέλους που εξαιρέθηκαν στις Ρυθμίσεις. + Αυτό θα εξαιρέσει το επιλεγμένο μαζί με τους υποφακέλους από την Απλή Συλλογή μόνο. Μπορείτε να διαχειριστείτε τους φακέλους που εξαιρέθηκαν στις Ρυθμίσεις. Να εξαιρεθεί μήπως ο γονικός φάκελος; - Εξαιρώντας τους φακέλους, θα τους αποκρύψει μαζί με τους υποφακέλους τους μόνο στο Simple Gallery, θα είναι ορατοί στις υπόλοιπες εφαρμογές.\n\nΑν θέλετε να τους αποκρύψετε και στις υπόλοιπες εφαρμογές, χρησιμοποιήστε την λειτουργία Απόκρυψη. + Εξαιρώντας τους φακέλους, θα τους αποκρύψει μαζί με τους υποφακέλους τους μόνο στην Απλή Συλλογή, θα είναι ορατοί στις υπόλοιπες εφαρμογές.\n\nΑν θέλετε να τους αποκρύψετε και στις υπόλοιπες εφαρμογές, χρησιμοποιήστε την λειτουργία Απόκρυψη. Διαγραφή όλων Να αφαιρεθούν όλοι οι φάκελοι από την λίστα των εξαιρεμένων; Αυτό δεν θα διαγράψει τους φακέλους. Κρυφοί φάκελοι @@ -63,6 +63,7 @@ Διαχείριση φακέλων που συμπεριλαμβάνονται Προσθήκη φακέλου Αν υπάρχουν κάποιοι φάκελοι που περιέχουν πολυμέσα, αλλά δεν αναγνωρίζονται από την εφαρμογή, μπορείτε να τους προσθέσετε χειροκίνητα εδώ.\n\nΗ προσθήκη στοιχείων εδώ, δεν θα εξαιρέσει κάποιον άλλο φάκελο. + Δεν βρέθηκαν αρχεία πολυμέσων. Μπορεί να λυθεί αυτό, προσθέτοντας τους φακέλους που περιέχουν αρχεία πολυμέσων με μη αυτόματο τρόπο. Αλλαγή μεγέθους @@ -93,7 +94,7 @@ Άλλο - Simple Wallpaper + Απλή Συλλογή Εφαρμογή ως ταπετσαρία Η εφαρμογή ως ταπετσαρία απέτυχε Εφαρμογή ως ταπετσαρία με: @@ -103,7 +104,7 @@ Αναλογία σε οριζόντια προβολή Αρχική οθόνη Οθόνη κλειδώματος - Αρχική οθόνη και κλειδώματος + Αρχική και Οθόνη Κλειδώματος Παρουσίαση διαφανιών @@ -112,12 +113,14 @@ Συμπερίληψη βίντεο Συμπερίληψη GIFs6 Τυχαία σειρά - Εφέ σταδιακής αλλαγής Κίνηση προς τα πίσω - Επανάληψη εμφάνισης διαφανιών + Επανάληψη εμφάνισης διαφανειών + Κινήσεις + Χωρίς + Εξασθένηση + Ολίσθηση Η εμφάνιση διαφανειών τελείωσε Δεν βρέθηκαν πολυμέσα για την εμφάνιση διαφανειών - Χρήση κίνησης εικόνων με διαγώνιο ξεθώριασμα Αλλαγή τύπου εμφάνισης @@ -130,7 +133,11 @@ Χωρίς Φάκελο Τελευταία τροπ/ηση + Τελευταία τροπ/ηση (ημερήσια) + Τελευταία τροπ/ηση (μηνιαία) Ημερομ. λήψης + Ημερομ. λήψης (ημερήσια) + Ημερομ. λήψης (μηνιαία) Τύπο αρχείου Επέκταση Σημειώστε ότι ομαδοποίηση και ταξινόμηση είναι 2 ανεξάρτητα πεδία @@ -192,9 +199,9 @@ Εναλλαγή προβολής αρχείου - Πώς μπορώ να κάνω το Simple Gallery προεπιλεγμένη εφαρμογή συλλογής πολυμέσων; + Πώς μπορώ να κάνω την Απλή Συλλογή προεπιλεγμένη εφαρμογή συλλογής πολυμέσων; Αρχικά πρέπει να βρείτε την τρέχουσα προεπιλεγμένη εφαρμογή γκάλερι στις Ρυθμίσεις (τμήμα Εφαρμογών) της συσκευής. Αναζητήστε για ένα κουμπί που αναφέρει κάτι σαν \"Άνοιγμα με προεπιλογή\", πατήστε το, μετά επιλέξτε \"Καθαρισμός προεπιλεγμένων\". - Την επόμενη φορά που θα προσπαθήσετε να ανοίξετε μία εικόνα ή ένα βίντεο θα πρέπει να δείτε έναν διάλογο επιλογής εφαρμογών, όπου μπορείτε να επιλέξετε Simple Gallery να το κάνετε προεπιλεγμένη εφαρμογή. + Την επόμενη φορά που θα προσπαθήσετε να ανοίξετε μία εικόνα ή ένα βίντεο θα πρέπει να δείτε έναν διάλογο επιλογής εφαρμογών, όπου μπορείτε να επιλέξετε Απλή Συλλογή να την κάνετε προεπιλεγμένη εφαρμογή. Κλείδωσα την εφαρμογή με κωδικό, αλλά τον ξέχασα. Τι μπορώ να κάνω; Υπάρχουν 2 λύσεις. Είτε επανεγκατάσταση της εφαρμογής, ή να εντοπίσετε την εφαρμογή στις ρυθμίσεις της συσκευής και να επιλέξετε \"Καθαρισμό δεδομένων\". Θα επαναφέρει όλες τις ρυθμίσεις και δεν θα σβήσει κάποιο αρχείο πολυμέσου. Πώς μπορώ να κάνω ένα άλμπουμ να φαίνεται στην κορυφή; @@ -202,7 +209,7 @@ Πώς μπορώ να τρέξω μπροστά (fast-forward) τα βίντεο; Μπορείτε είτε να σύρετε το δάχτυλό σας οριζόντια πάνω από το πρόγραμμα αναπαραγωγής Βίντεο ή να κάνετε κλικ στα γράμματα της τρέχουσας ή της μέγιστης διάρκειας κοντά στο Γραμμή Αναζήτησης. Αυτό θα μετακινήσει το βίντεο προς τα πίσω ή προς τα εμπρός. Ποια είναι διαφορά μεταξύ απόκρυψης και εξαίρεσης ενός φακέλου; - Η εξαίρεση δεν επιτρέπει την εμφάνιση του φακέλου μόνο στο Simple Gallery, ενώ η απόκρυψη λειτουργεί σε επίπεδο συστήματος και θα αποκρύψει τον φάκελο και από άλλες εφαρμογές γκάλερι. Λειτουργεί δημιουργώντας ένα άδειο \".nomedia\" αρχείο στον επιλεγμένο φάκελο, το οποίο μπορείτε να το διαγράψετε και με οποιονδήποτε διαχειριστή αρχείων. + Η εξαίρεση δεν επιτρέπει την εμφάνιση του φακέλου μόνο στην Απλή Συλλογή, ενώ η απόκρυψη λειτουργεί σε επίπεδο συστήματος και θα αποκρύψει τον φάκελο και από άλλες εφαρμογές γκάλερι. Λειτουργεί δημιουργώντας ένα άδειο \".nomedia\" αρχείο στον επιλεγμένο φάκελο, το οποίο μπορείτε να το διαγράψετε και με οποιονδήποτε διαχειριστή αρχείων. Γιατί εμφανίζονται φάκελοι με εξώφυλλο μουσικής ή αυτόκολλητα; Είναι πιθανόν να δείτε κάποια περίεργα άλμπουμ να εμφανίζονται. Μπορείτε να τα εξαιρέσετε εύκολα με παρατεταμένο άγγιγμα και επιλογή του Εξαίρεση. Στον επόμενο διάλογο μπορείτε να επιλέξετε επάνω φάκελο. Είναι πιθανό να μην επιτρέψει την εμφάνιση και άλλων σχετικών άλμπουμ. Ένας φάκελος με εικόνες δεν εμφανίζεται. Τι μπορώ να κάνω; @@ -225,27 +232,27 @@ - Απλή Συλλογή Pro: Διαχείριση & Επεξεργασία + ΑΠΛΗ ΣΥΛΛΟΓΗ Pro: Διαχείριση & Επεξεργασία - Μια Offline gallery χωρίς διαφ/σεις. Επεξεργασία ανάκτηση προστασία Φωτό-Βίντεο + Μια Offline Συλλογή χωρίς διαφ/σεις. Επεξεργασία ανάκτηση προστασία Φωτό-Βίντεο - Η Simple Gallery Pro είναι εκτός σύνδεσης και εξαιρετικά προσαρμόσιμη. Οργανώστε και επεξεργαστείτε τις φωτογραφίες σας, ανακτήσετε διαγραμμένα αρχεία απο τον κάδο ανακύκλωσης, προστατεύσετε και αποκρύψτε αρχεία, προβάλετε πλήθος διαφορετικών φωτογραφιών και μορφών βίντεο, συμπεριλαμβανομένων των RAW, SVG και πολλών άλλων. + Η Απλή Συλλογή Pro είναι εκτός σύνδεσης και εξαιρετικά προσαρμόσιμη. Οργανώστε και επεξεργαστείτε τις φωτογραφίες σας, ανακτήσετε διαγραμμένα αρχεία απο τον κάδο ανακύκλωσης, προστατεύσετε και αποκρύψτε αρχεία, προβάλετε πλήθος διαφορετικών φωτογραφιών και μορφών βίντεο, συμπεριλαμβανομένων των RAW, SVG και πολλών άλλων. Η εφαρμογή δεν περιέχει διαφημίσεις και περιττά δικαιώματα. Εφόσον δεν απαιτεί πρόσβαση στο διαδίκτυο, έτσι προστατεύεται το απόρρητό σας. ------------------------------------------------- - ΧΑΡΑΚΤΗΡΙΣΤΙΚΑ-SIMPLE GALLERY PRO + ΧΑΡΑΚΤΗΡΙΣΤΙΚΑ-ΑΠΛΗΣ ΣΥΛΛΟΓΗΣ PRO ------------------------------------------------- • Εκτός σύνδεσης χωρίς διαφημίσεις ή αναδυόμενα παράθυρα - • Simple gallery photo editor – κόψιμο, περιστροφή, αλλαγή μεγέθους, σχεδίαση, φίλτρα και άλλα + • Απλής Συλλογής Επεξεργαστής – κόψιμο, περιστροφή, αλλαγή μεγέθους, σχεδίαση, φίλτρα και άλλα • Δεν απαιτείται πρόσβαση στο διαδίκτυο, παρέχοντας μεγαλύτερη προστασία της ιδιωτικής ζωής και ασφάλειας • Δεν απαιτούνται περιττά δικαιώματα • Γρήγορη αναζήτηση εικόνων, βίντεο και αρχείων • Άνοιγμα και προβολή πολλών διαφορετικών τύπων φωτογραφιών και βίντεο (RAW, SVG, πανοραμική κλπ) • Μια ποικιλία διαισθητικών χειρονομιών για εύκολη επεξεργασία και οργάνωση αρχείων • Πολλοί τρόποι για φιλτράρισμα, ομαδοποίησης και ταξινόμησης αρχείων - • Προσαρμογή εμφάνισης του Simple Gallery Pro + • Προσαρμογή εμφάνισης της Απλής Συλλογής Pro • Διατίθεται σε 32 γλώσσες • Σημειώστε τα αρχεία ως αγαπημένα για γρήγορη πρόσβαση • Προστατέψτε τις φωτογραφίες σας και βίντεο με μοτίβο, κωδικό ή δακτυλικό αποτύπωμα @@ -254,20 +261,20 @@ • Εναλλαγή προβολής αρχείων για απόκρυψη φωτογραφιών και Βίντεο • Δημιουργήστε μια προσαρμόσιμη παρουσίαση των αρχείων σας • Δείτε λεπτομερείς πληροφορίες των αρχείων σας (ανάλυση, τιμές EXIF κλπ.) - • Η Simple Gallery Pro είναι ανοικτού κώδικα + • Η Απλή Συλλογή Pro είναι ανοικτού κώδικα … και πάρα πολλά ακόμα! - ΕΞΕΡΓΑΣΤΗΣ PHOTO GALLERY - Η Simple Gallery Pro σας διευκολύνει να επεξεργαστείτε τις φωτογραφίες σας άμεσα. Περικοπή, αναστροφή, περιστροφή και αλλαγή μεγέθους των εικόνων σας. Εάν αισθάνεστε λίγο πιο δημιουργικοί, μπορείτε να προσθέσετε φίλτρα και σχεδίαση στις φωτογραφίες σας! + ΕΞΕΡΓΑΣΤΗΣ ΑΠΛΗΣ ΣΥΛΛΟΓΗΣ + Η Απλή Συλλογή Pro σας διευκολύνει να επεξεργαστείτε τις φωτογραφίες σας άμεσα. Περικοπή, αναστροφή, περιστροφή και αλλαγή μεγέθους των εικόνων σας. Εάν αισθάνεστε λίγο πιο δημιουργικοί, μπορείτε να προσθέσετε φίλτρα και σχεδίαση στις φωτογραφίες σας! ΥΠΟΣΤΗΡΙΞΗ ΠΟΛΛΩΝ ΤΥΠΩΝ ΑΡΧΕΙΩΝ - Σε αντίθεση με κάποιες άλλες εφαρμογές η Simple Gallery Pro υποστηρίζει ένα τεράστιο φάσμα διαφορετικών τύπων αρχείων, όπως JPEG, PNG, MP4, MKV, RAW, SVG, Πανοραμικές φωτογραφίες, βίντεο πανοραμικών και πολλά άλλα. + Σε αντίθεση με κάποιες άλλες εφαρμογές η Απλή Συλλογή Pro υποστηρίζει ένα τεράστιο φάσμα διαφορετικών τύπων αρχείων, όπως JPEG, PNG, MP4, MKV, RAW, SVG, Πανοραμικές φωτογραφίες, βίντεο πανοραμικών και πολλά άλλα. - ΠΟΛΥ ΠΡΟΣΑΡΜΟΣΙΜΟΣ ΔΙΑΧΕΙΡΙΣΤΗΣ GALLERY - Από το UI στα κουμπιά λειτουργιών στην κάτω γραμμή εργαλείων, η Simple Gallery Pro είναι ιδιαίτερα προσαρμόσιμη και λειτουργεί όπως εσείς θέλετε. Καμιά άλλη εφαρμογή δεν έχει τέτοια ευελιξία! Χάρη στον ανοιχτό κώδικα, είναι επίσης διαθέσιμη σε 32 γλώσσες! + ΠΟΛΥ ΠΡΟΣΑΡΜΟΣΙΜΟΣ ΔΙΑΧΕΙΡΙΣΤΗΣ ΣΥΛΛΟΓΗΣ + Από το UI στα κουμπιά λειτουργιών στην κάτω γραμμή εργαλείων, η Απλή Συλλογή Pro είναι ιδιαίτερα προσαρμόσιμη και λειτουργεί όπως εσείς θέλετε. Καμιά άλλη εφαρμογή δεν έχει τέτοια ευελιξία! Χάρη στον ανοιχτό κώδικα, είναι επίσης διαθέσιμη σε 32 γλώσσες! ΕΠΑΝΑΦΟΡΑ ΔΙΑΓΡΑΜΕΝΩΝ ΦΩΤΟ ΚΑΙ ΒΙΝΤΕΟ - Διαγράψατε τυχαία μια πολύτιμη φωτογραφία ή βίντεο; Μην ανησυχείτε! Η Simple Gallery Pro διαθέτει έναν εύχρηστο κάδο ανακύκλωσης όπου μπορείτε να ανακτήσετε τις διαγραμμένες φωτογραφίες και βίντεο πανεύκολα. + Διαγράψατε τυχαία μια πολύτιμη φωτογραφία ή βίντεο; Μην ανησυχείτε! Η Απλή Συλλογή Pro διαθέτει έναν εύχρηστο κάδο ανακύκλωσης όπου μπορείτε να ανακτήσετε τις διαγραμμένες φωτογραφίες και βίντεο πανεύκολα. ΠΡΟΣΤΑΣΙΑ ΚΑΙ ΑΠΟΚΡΥΨΗ ΑΡΧΕΙΩΝ ΦΩΤΟ ΚΑΙ ΒΙΝΤΕΟ Χρησιμοποιώντας κωδικό, μοτίβο ή τον σαρωτή δακτυλικών αποτυπωμάτων της συσκευής σας, μπορείτε να προστατεύσετε και να αποκρύψετε φωτογραφίες, βίντεο ή ολόκληρα άλμπουμ. Μπορείτε να προστατεύσετε την ίδια την εφαρμογή ή να κλειδώσετε συγκεκριμένες λειτουργίες της. Για παράδειγμα, δεν μπορείτε να διαγράψετε ένα αρχείο χωρίς χρήση των δακτυλικών αποτυπωμάτων, συμβάλλοντας στην προστασία των αρχείων σας από τυχαία διαγραφή. diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 194364f59..ee6efe0bc 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -63,6 +63,7 @@ Gestionar carpetas incluidas Agregar carpeta Si tiene algunas carpetas que contengan multimedia, pero que no fueron reconocidas por la aplicación, puede agregarlas manualmente aquí. + No media files have been found. You can solve it by adding the folders containing media files manually. Redimensionar @@ -112,12 +113,14 @@ Incluir vídeos Incluir GIFs Orden aleatorio - Usar animaciones de desvanecimiento Mover hacia atrás Presentación de diapositivas + Animación + Ninguna + Fusión + Desplazamineto La diapositiva terminó No se han encontrado medios para la presentación de diapositivas - Usa animaciones de crossfade. Cambiar tipo de vista @@ -130,7 +133,11 @@ No agrupar ficheros Carpeta Último modificado - Data de toma + Último modificado (diario) + Último modificado (mensual) + Fecha de toma + Fecha de toma (diario) + Fecha de toma (mensual) Tipo de fichero Extensión Tenga en cuenta que la agrupación y la clasificación son 2 campos independientes diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index c2775cecd..737c12e5c 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -63,6 +63,7 @@ Hallitse sisällettyjä kansioita Lisää kansio Jos sinulla on kansioita, jotka sisältää mediaa, mutta sovellus ei tunnistanut, voit lisätä ne manuaalisesti tähän.\n\Lisääminen ei poissulje muita kansioita. + No media files have been found. You can solve it by adding the folders containing media files manually. Rajaa @@ -112,12 +113,14 @@ Sisällytä Videot Sisällytä GIFit Satunnainen järjestys - Käytä häivitys-animaatiota Liiku takaisinpäin Jatkuva diaesitys + Animation + None + Fade + Slide Diaesitys päättyi Mediaa diaesitykseen ei löytynyt - Use crossfade animations Vaihda näkymää @@ -130,7 +133,11 @@ Do not group files Folder Last modified + Last modified (daily) + Last modified (monthly) Date taken + Date taken (daily) + Date taken (monthly) File type Extension Please note that grouping and sorting are 2 independent fields diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index de4a03228..0e0a9a9ba 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -63,6 +63,7 @@ Gérer les dossiers ajoutés Ajouter un dossier Si vous avez des dossiers contenant des médias qui ne sont pas affichés dans l\'application, vous pouvez les ajouter manuellement ici.\n\nCet ajout n\'exclura aucun autre dossier. + Aucun fichier multimédia n\'a été trouvé. Vous pouvez ajouter manuellement des dossiers contenant des fichiers multimédia. Redimensionner @@ -112,12 +113,14 @@ Inclure les vidéos Inclure les GIFs Ordre aléatoire - Utiliser un fondu Défilement inverse Diaporama en boucle + Animation + None + Fade + Slide Diaporama terminé Aucun média trouvé pour le diaporama - Utiliser des animations en fondu enchaîné Changer de mode d\'affichage @@ -130,7 +133,11 @@ Ne pas grouper les fichiers Dossier Date de modification + Last modified (daily) + Last modified (monthly) Date de prise de vue + Date taken (daily) + Date taken (monthly) Type de fichier Extension Notez que grouper et trier sont 2 modes de tri indépendants @@ -167,7 +174,7 @@ Cacher les informations supplémentaires si la barre d\'état est masquée Afficher les boutons d\'action Afficher la corbeille en vue \"Dossier\" - Niveau de zoom maximal des images + Niveau de zoom Afficher les images avec la meilleur qualité possible Afficher la corbeille en fin de liste sur l\'écran principal Fermer la vue plein écran par un geste vers le bas @@ -218,8 +225,8 @@ La solution actuelle d\'affichage des images fonctionne bien dans la grande majorité des cas, mais si vous voulez une qualité d\'image encore meilleure, vous pouvez activer l\'option \"Afficher les images avec la plus haute qualité possible\" dans la section \"Niveau de zoom maximal des images\" des paramètres de l\'application. J\'ai caché un fichier ou un dossier. Comment puis-je en rétablir l\'affichage ? Vous pouvez soit appuyer sur l\'option \"Afficher les fichiers cachés\" du menu de l\'écran principal, ou appuyer sur le bouton \"Afficher les éléments cachés\" dans les paramètres de l\'application. Si vous voulez rétablir leur affichage, effectuez un appui prolongé dessus et appuyez sur le symbole \"Œil\" permettant l\'affichage. Les dossiers sont cachés en ajoutant un fichier \".nomedia\" à leur racine, vous pouvez également supprimer ce fichier avec n\’importe quel explorateur de fichiers. - Why does the app take up so much space? - App cache can take up to 250MB, it ensures quicker image loading. If the app is taking up even more space, it is most likely caused by you having items in the Recycle Bin. Those files count to the app size. You can clear the Recycle bin by opening it and deleting all files, or from the app settings. Every file in the Bin is deleted automatically after 30 days. + Pourquoi l\'application prend-elle tant de place ? + Le cache d\'application peut prendre jusqu\'à 250 Mo pour accélérer le chargement des images. Si l\'application occupe encore plus d\'espace, c\'est probablement parce que vous avez des éléments dans la corbeille. Ces fichiers comptent pour la taille de l\'application. Vous pouvez vider la corbeille en l\'ouvrant et en supprimant tous les fichiers ou à partir des paramètres de l\'application. Chaque fichier de la corbeille est automatiquement supprimé après 30 jours. diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 2055bd6ef..a01d46cc3 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -63,6 +63,7 @@ Xestionar cartafoles incluídos Engadir cartafol Si ten algún cartafol con medios, mais non foi recoñecido polo aplicativo, pódeo engadir manualmente.\n\nEngadindo aquí elementos non eliminará outros. + No media files have been found. You can solve it by adding the folders containing media files manually. Redimensionar @@ -112,12 +113,14 @@ Incluír vídeos Incluír GIFs Orde aleatoria - Utilizar animación esvaescente Mover atrás Reproducir en bucle + Animation + None + Fade + Slide Rematou a presentación Non se atoparon medios para a presentación - Use crossfade animations Cambiar o tipo de vista @@ -130,7 +133,11 @@ Non agrupar ficheiros Cartafol Último modificado + Last modified (daily) + Last modified (monthly) Data de captura + Date taken (daily) + Date taken (monthly) Tipo de ficheior Extensión Please note that grouping and sorting are 2 independent fields diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 081714f73..cd8831065 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -63,6 +63,7 @@ Upravljajte uključenim mapama Dodaj mapu Ako imate neke mape koje sadrže medije, ali ih aplikacija nije prepoznala, ručno ih možete dodati ovdje.\n\nDodavanjem nekih stavki ovdje nećete izuzeti bilo koju drugu mapu. + No media files have been found. You can solve it by adding the folders containing media files manually. Promjeni veličinu @@ -112,12 +113,14 @@ Dodaj videe Dodaj GIF-ove Nasumični redoslijed - Koristi animaciju izbljeđivanja Pomakni unatrag Prikaži dijaprojekciju kao petlju + Animation + None + Fade + Slide Kraj dijaprojekcije Nema datoteka za dijaprojekciju - Koristi prijelazne animacije Promijeni vrstu prikaza @@ -130,7 +133,11 @@ Nemoj grupirati ove datoteke Mapa Zadnje uređivano + Last modified (daily) + Last modified (monthly) Datum snimanja + Date taken (daily) + Date taken (monthly) Tip datoteke Vrsta datoteke Please note that grouping and sorting are 2 independent fields diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index a6a7e03b0..95b0f32cf 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -63,6 +63,7 @@ Befoglalt mappák kezelése Mappa hozzáadása Ha vannak olyan mappák, amelyek média fájlokat tartalmaznak, de az alkalmazás nem ismerte fel, akkor kézzel is hozzáadhatja ezeket.\n\nAz elemek hozzáadása nem zár ki más mappákat. + Nem talált médiafájlokat. Ezt megoldhatja a médiafájlokat tartalmazó mappák manuális hozzáadásával. Átméretezés @@ -113,12 +114,14 @@ Videók befoglalása GIF befoglalása Véletlen sorrend - Halványuló animáció használat Áthelyezés hátra Diavetítés ismétlése + Animation + None + Fade + Slide A diavetítés vége A diavetítéshez nem található média - Animáció átmenet használat Nézet típus változtatása @@ -131,10 +134,14 @@ Nincs csoportosítás Mappa Utolsó módosítás + Last modified (daily) + Last modified (monthly) Dátum + Date taken (daily) + Date taken (monthly) Fájl típus Kiterjesztés - Please note that grouping and sorting are 2 independent fields + Kérjük, vegye figyelembe, hogy a csoportosítás és a rendezés 2 egymástól független mező Mappa mutatása a widgeten: diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 2343f3803..34eb6a5af 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -2,7 +2,7 @@ Simple Gallery Galeri - Edit + Sunting Buka kamera (tersembunyi) (dikecualikan) @@ -26,13 +26,13 @@ Aktifkan rotasi Ubah orientasi Paksa potret - Paksa landscape + Paksa lanskap Gunakan orientasi default Perbaiki Tanggal Diambil Memperbaiki… Tanggal berhasil diperbaiki - Share a resized version - Hey,\n\nseems like you upgraded from the old free app. You can now uninstall the old version, which has an \'Upgrade to Pro\' button at the top of the app settings.\n\nYou will only have the Recycle bin items deleted, favorite items unmarked and you will also have to reset your app settings.\n\nThanks! + Bagikan versi yang diubah ukurannya + Hai,\n\nsepertinya anda memperbarui dari aplikasi gratis versi lama. Anda sekarang bisa mencopot versi yang lama, yang ada tombol \'Tingkatkan ke Pro\' di bagian atas pengaturan aplikasi.\n\nHanya item Keranjang sampah yang akan dihapus, item favorit menjadi tak bertanda dan anda juga harus menyetel ulang pengaturan aplikasi.\n\nThanks! Filter media @@ -41,28 +41,29 @@ GIF Gambar RAW SVG - Tidak ada file media ditemukan dari filter ini. + Tidak ada berkas media ditemukan dari filter ini. Ubah filter - Fungsi ini menyembunyikan folder dengan menambahkan file \'.nomedia\' ke dalamnya, juga akan menyembunyikan semua subfolder. Anda bisa melihatnya dari opsi \'Tampilkan file tersembunyi\' di Setelan. Lanjutkan? + Fungsi ini menyembunyikan folder dengan menambahkan berkas \'.nomedia\' ke dalamnya, juga akan menyembunyikan semua subfolder. Anda bisa melihatnya dari opsi \'Tampilkan berkas tersembunyi\' di Pengaturan. Lanjutkan? Kecualikan Folder yang dikecualikan Atur folder yang dikecualikan - Ini hanya akan mengecualikan pilihan bersama dengan subfoldernya di Simple Gallery. Anda bisa mengatur pengecualian di Setelan. + Ini hanya akan mengecualikan pilihan bersama dengan subfoldernya di Simple Gallery. Anda bisa mengatur pengecualian di Pengaturan. Kecualikan folder induk? - Mengecualikan folder akan membuatnya bersama subfoldernya tersembunyi hanya di Simple Gallery, namun masih bisa dilihat di aplikasi lain.\n\nJika Anda ingin menyembunyikannya dari aplikasi lain juga, gunakan fitur Sembunyikan. + Mengecualikan folder akan membuatnya bersama subfoldernya tersembunyi hanya di Simple Gallery, namun masih bisa dilihat di aplikasi lain.\n\nJika anda ingin menyembunyikannya dari aplikasi lain juga, gunakan fitur Sembunyikan. Bersihkan daftar Hapus semua folder dari daftar pengecualian? Ini tidak akan menghapus folder tersebut. Folder tersembunyi Atur folder tersembunyi - Sepertinya tidak ada folder tersembunyi dengan file \".nomedia\" didalamnya. + Sepertinya tidak ada folder tersembunyi dengan berkas \".nomedia\" didalamnya. Folder yang disertakan Atur folder yang disertakan Tambah folder - Jika ada folder yang berisi file media, namun tidak dikenali oleh aplikasi ini, Anda bisa menambahkannya disini secara manual.\n\nMenambah beberapa item disini tidak akan mengecualikan folder yang lain. + Jika ada folder yang berisi berkas media, namun tidak dikenali oleh aplikasi ini, anda bisa menambahkannya disini secara manual.\n\nMenambah beberapa item disini tidak akan mengecualikan folder yang lain. + Tidak ada berkas media yang ditemukan. Anda bisa memperbaikinya dengan menambahkan folder yang berisi berkas media secara manual. Ubah ukuran @@ -73,16 +74,16 @@ Harap masukkan resolusi dengan benar - Editor + Penyunting Simpan Rotasi Jalur Jalur gambar tidak valid - Gagal mengedit gambar - Edit dengan: - Tidak ada aplikasi editor gambar - Lokasi file tidak diketahui - Tidak dapat mengganti file sumber + Gagal menyunting gambar + Sunting dengan: + Tidak ada aplikasi penyunting gambar + Lokasi berkas tidak diketahui + Tidak bisa mengganti berkas sumber Putar ke kiri Putar ke kanan Putar 180º @@ -100,7 +101,7 @@ Menyetel wallpaper… Wallpaper berhasil disetel Aspek rasio potret - Aspek rasio landscape + Aspek rasio lanskap Layar beranda Layar kunci Beranda dan layar kunci @@ -112,37 +113,43 @@ Sertakan video Sertakan GIF Urutan acak - Animasi memudar Mundur Slideshow tanpa henti + Animation + None + Fade + Slide Slideshow berakhir Tidak ditemukan media untuk slideshow - Use crossfade animations Ubah jenis tampilan Kotak Daftar - Kelompokkan langsung subfolder + Kelompokkan subfolder langsung Kelompokkan menurut - Jangan kelompokkan file + Jangan kelompokkan berkas Folder Terakhir diubah + Last modified (daily) + Last modified (monthly) Tanggal diambil - Jenis file + Date taken (daily) + Date taken (monthly) + Jenis berkas Ekstensi - Please note that grouping and sorting are 2 independent fields + Harap dicatat bahwa mengelompokkan dan mengurutkan adalah 2 ruas yang berbeda - Folder shown on the widget: - Show folder name + Folder yang ditampilkan pada widget: + Tampilkan nama folder Putar video otomatis Ingat posisi pemutaran terakhir - Tampil/sembunyikan nama file + Tampil/sembunyikan nama berkas Ulangi video Animasi GIF di thumbnail Kecerahan maksimal saat melihat di layar penuh @@ -171,67 +178,67 @@ Tampilkan gambar dalam kualitas tertinggi Tampilkan Sampah sebagai item terakhir di layar utama Izinkan keluar dari layar penuh dengan menggeser kebawah - Allow 1:1 zooming in with two double taps - Always open videos on a separate screen with new horizontal gestures - Show a notch if available - Allow rotating images with gestures - File loading priority - Speed - Compromise - Avoid showing invalid files + Izinkan pembesaran 1:1 dengan dua kali ketuk + Selalu buka video pada layar terpisah dengan gestur horizontal baru + Tampilkan notch jika tersedia + Izinkan memutar gambar dengan gestur + Prioritas pemuatan berkas + Kecepatan + Kompromi + Hindari menampilkan berkas yang tidak valid Thumbnail Media layar penuh Detail tambahan - Tindakan di bawah + Tindakan bawah Sesuaikan tombol tindakan bawah Favorit - Tampil/sembunyikan file + Tampil/sembunyikan berkas Bagaimana cara menjadikan Simple Gallery sebagai aplikasi galeri default? - Pertama Anda harus menemukan galeri default saat ini di bagian Aplikasi di Setelan perangkat, lihatlah tombol yang seperti \"Buka secara default\", klik itu, lalu pilih \"Hapus default\". - Lain kali Anda mencoba membuka gambar atau video, Anda akan disuruh memilih aplikasi, dimana Anda bisa memilih Simple Gallery dan menjadikannya default. - Saya mengunci aplikasi dengan password, tapi saya lupa. Apa yang harus dilakukan? - Anda bisa menyelesaikannya dengan 2 cara. Anda bisa instal ulang aplikasi, atau cari aplikasi ini di Setelan perangkat dan pilih \"Hapus data\". Ini akan menyetel ulang semua setelan Anda, dan tidak akan menghapus file media apapun. + Pertama anda harus menemukan galeri default saat ini di bagian Aplikasi di Pengaturan perangkat, lihatlah tombol yang seperti \"Buka secara default\", klik itu, lalu pilih \"Hapus default\". + Lain kali anda mencoba membuka gambar atau video, anda akan disuruh memilih aplikasi, dan anda bisa memilih Simple Gallery dan menjadikannya default. + Saya mengunci aplikasi dengan sandi, tapi saya lupa. Apa yang harus dilakukan? + Anda bisa menyelesaikannya dengan 2 cara. Anda bisa pasang ulang aplikasi, atau cari aplikasi ini di Pengaturan perangkat dan pilih \"Hapus data\". Ini akan menyetel ulang semua pengaturan anda, dan tidak akan menghapus berkas media apapun. Bagaimana agar sebuah album selalu muncul paling atas di daftar? Anda bisa menekan lama album tersebut dan pilih ikon Pin di menu tindakan, itu akan menaruhnya di atas daftar. Anda juga bisa menyematkan beberapa folder, item yang di-pin akan diurutkan berdasarkan metode urutan default. Bagaimana cara mempercepat laju video? You can either drag your finger horizontally over the video player, or click on the current or max duration texts near the seekbar. That will move the video either backward, or forward. Apa perbedaan antara menyembunyikan dan mengecualikan folder? - Mengecualikan tidak akan menampilkan folder di Simple Gallery, sedangkan Sembunyikan bekerja sesuai aturan sistem dan akan menyembunyikan folder juga dari aplikasi galeri yang lain. Cara kerjanya dengan membuat file \".nomedia\" kosong pada folder yang diinginkan, yang bisa Anda hapus juga dengan aplikasi file manager. + Mengecualikan tidak akan menampilkan folder di Simple Gallery, sedangkan Sembunyikan bekerja sesuai aturan sistem dan akan menyembunyikan folder juga dari aplikasi galeri yang lain. Cara kerjanya dengan membuat berkas \".nomedia\" kosong pada folder yang diinginkan, yang bisa anda hapus juga dengan aplikasi pengelola berkas. Mengapa folder dengan gambar album musik atau stiker muncul? - Kadang Anda melihat beberapa album yang tidak biasa muncul. Anda bisa dengan mudah menyembunyikannya dengan menekan lama dan pilih Kecualikan. Pada dialog berikutnya, Anda lalu bisa memilih folder induk, yang akan mencegah album terkait muncul kembali. + Kadang anda melihat beberapa album yang tidak biasa muncul. Anda bisa dengan mudah menyembunyikannya dengan menekan lama dan pilih Kecualikan. Pada dialog berikutnya, anda lalu bisa memilih folder induk, yang akan mencegah album terkait muncul kembali. Ada folder berisi gambar namun tidak muncul, apa yang harus dilakukan? - Itu bisa disebabkan berbagai alasan, namun solusinya mudah. Pergi ke Setelan -> Atur folder yang disertakan, pilih Tambah dan cari folder yang diinginkan. + Itu bisa disebabkan berbagai alasan, namun solusinya mudah. Pergi ke Pengaturan -> Atur folder yang disertakan, pilih Tambah dan cari folder yang diinginkan. Bagaimana jika saya hanya ingin beberapa folder saja yang terlihat? - Menambahkan folder di Folder yang Disertakan tidak otomatis mengecualikan folder yang lain. Yang bisa Anda lakukan adalah pergi ke Setelan -> Atur Folder yang Dikecualikan, lalu kecualikan folder root \"/\", lalu tambahkan folder yang diinginkan di Setelan -> Atur Folder yang Disertakan. + Menambahkan folder di Folder yang Disertakan tidak otomatis mengecualikan folder yang lain. Yang bisa anda lakukan adalah pergi ke Pengaturan -> Atur Folder yang Dikecualikan, lalu kecualikan folder root \"/\", lalu tambahkan folder yang diinginkan di Pengaturan -> Atur Folder yang Disertakan. Itu akan membuat folder yang dipilih saja yang muncul, dan jika sebuah folder disertakan dan dikecualikan secara bersamaan, folder tersebut akan muncul. Bisakah saya meng-crop gambar dengan aplikasi ini? - Ya, Anda bisa melakukannya di Editor, dengan menyeret sudut gambar. Anda bisa masuk ke editor dengan menekan lama thumbnail gambar dan memilih Edit, atau pilih Edit dari tampilan layar penuh. - Bisakah saya mengelompokkan thumbnail file media? - Bisa, gunakan menu \"Kelompokkan menurut\" pada tampilan thumbnail. Anda bisa mengelompokkan file dengan berbagai kriteria, termasuk Tanggal Diambil. Jika Anda menggunakan fungsi \"Tampilkan semua isi folder\", Anda juga bisa mengelompokkan berdasarkan foldernya. - Tidak dapat mengurutkan berdasarkan Tanggal Diambil, bagaimana cara memperbaikinya? - Itu umumnya disebabkan karena file yang disalin dari tempat lain. Anda bisa memperbaikinya dengan memilih thumbnail file dan pilih \"Perbaiki Tanggal Diambil\". + Ya, anda bisa melakukannya di Penyunting, dengan menyeret sudut gambar. Anda bisa masuk ke penyunting dengan menekan lama thumbnail gambar dan memilih Sunting, atau pilih Sunting dari tampilan layar penuh. + Bisakah saya mengelompokkan thumbnail berkas media? + Bisa, gunakan menu \"Kelompokkan menurut\" pada tampilan thumbnail. Anda bisa mengelompokkan berkas dengan berbagai kriteria, termasuk Tanggal Diambil. Jika anda menggunakan fungsi \"Tampilkan semua isi folder\", anda juga bisa mengelompokkan berdasarkan foldernya. + Tidak bisa mengurutkan berdasarkan Tanggal Diambil, bagaimana cara memperbaikinya? + Itu umumnya disebabkan karena berkas yang disalin dari tempat lain. Anda bisa memperbaikinya dengan memilih berkas thumbnail dan pilih \"Perbaiki Tanggal Diambil\". Saya melihat beberapa pita warna pada gambar. Bagaimana saya meningkatkan kualitasnya? - Solusi saat ini untuk menampilkan gambar berfungsi dengan baik dalam sebagian besar kasus, namun jika Anda ingin kualitas gambar yang lebih baik, Anda bisa mengaktifkan \"Tampilkan gambar dalam kualitas tertinggi\" di setelan aplikasi, pada bagian \"Zoom gambar mendalam\". - Saya punya file/folder tersembunyi. Bagaimana cara memunculkannya? - Anda bisa memilih menu \"Tampilkan sementara file tersembunyi\" di layar utama, atau \"Tampilkan file tersembunyi\" di setelan aplikasi untuk menampilkannya. Jika Anda tidak ingin menyembunyikannya, tekan lama dan pilih \"Jangan sembunyikan\". Folder disembunyikan dengan menambahkan file \".nomedia\" di dalamnya, Anda bisa menghapus file tersebut dengan aplikasi file manager. - Why does the app take up so much space? - App cache can take up to 250MB, it ensures quicker image loading. If the app is taking up even more space, it is most likely caused by you having items in the Recycle Bin. Those files count to the app size. You can clear the Recycle bin by opening it and deleting all files, or from the app settings. Every file in the Bin is deleted automatically after 30 days. + Solusi saat ini untuk menampilkan gambar berfungsi dengan baik dalam sebagian besar kasus, namun jika anda ingin kualitas gambar yang lebih baik, anda bisa mengaktifkan \"Tampilkan gambar dalam kualitas tertinggi\" di pengaturan aplikasi, pada bagian \"Zoom gambar mendalam\". + Saya punya berkas/folder tersembunyi. Bagaimana cara memunculkannya? + Anda bisa memilih menu \"Tampilkan sementara berkas tersembunyi\" di layar utama, atau \"Tampilkan berkas tersembunyi\" di pengaturan aplikasi untuk menampilkannya. Jika anda tidak ingin menyembunyikannya, tekan lama dan pilih \"Jangan sembunyikan\". Folder disembunyikan dengan menambahkan berkas \".nomedia\" di dalamnya, anda bisa menghapus berkas tersebut dengan aplikasi pengelola berkas. + Kenapa aplikasi menggunakan sangat banyak ruang kosong? + Cache aplikasi bisa mencapai 250MB, ini untuk menjamin pemuatan gambar yang lebih cepat. Jika aplikasi menggunakan lebih banyak lagi ruang kosong, sangat memungkinkan anda memiliki item di dalam Keranjang Sampah. Berkas tersebut akan menambah ukuran aplikasi. Anda bisa mengosongkan Keranjang sampah dengan cara membukanya dan menghapus semua berkas, atau dari pengaturan aplikasi. Semua berkas di dalam keranjang sampah akan otomatis dihapus setelah 30 hari. - Simple Gallery Pro: Photo Manager & Editor + Simple Gallery Pro: Pengelola & Penyunting Foto - Offline gallery without ads. Organize, edit, recover and protect photos & videos + Galeri luring tanpa iklan. Kelola, sunting, pulihkan dan lindungi foto & video - Simple Gallery Pro is a highly customizable offline gallery. Organize & edit your photos, recover deleted files with the recycle bin, protect & hide files and view a huge variety of different photo & video formats including RAW, SVG and much more. + Simple Gallery Pro adalah aplikasi galeri luring yang sangat mudah diubahsuai. Mengelola & menyunting foto anda, memulihkan berkas yang terhapus dari keranjang sampah, melindungi & menyembunyikan berkas, dan menampilkan banyak format foto & video, diantaranya RAW, SVG dan masih banyak lainnya. - The app contains no ads and unnecessary permissions. As the app doesn’t require internet access either, your privacy is protected. + Aplikasi sama sekali tidak berisi iklan dan tidak membutuhkan perizinan yang tidak perlu. Dan karena aplikasi juga tidak membutuhkan akses internet, privasi anda terlindungi. ------------------------------------------------- SIMPLE GALLERY PRO – FEATURES diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml new file mode 100644 index 000000000..34eb6a5af --- /dev/null +++ b/app/src/main/res/values-in/strings.xml @@ -0,0 +1,296 @@ + + + Simple Gallery + Galeri + Sunting + Buka kamera + (tersembunyi) + (dikecualikan) + Pin folder + Lepas pin folder + Pin ke atas + Tampilkan semua isi folder + Semua folder + Beralih ke tampilan folder + Folder lain + Tampilkan di peta + Lokasi tidak diketahui + Tambah jumlah kolom + Kurangi jumlah kolom + Ubah sampul + Pilih foto + Gunakan default + Volume + Kecerahan + Kunci rotasi + Aktifkan rotasi + Ubah orientasi + Paksa potret + Paksa lanskap + Gunakan orientasi default + Perbaiki Tanggal Diambil + Memperbaiki… + Tanggal berhasil diperbaiki + Bagikan versi yang diubah ukurannya + Hai,\n\nsepertinya anda memperbarui dari aplikasi gratis versi lama. Anda sekarang bisa mencopot versi yang lama, yang ada tombol \'Tingkatkan ke Pro\' di bagian atas pengaturan aplikasi.\n\nHanya item Keranjang sampah yang akan dihapus, item favorit menjadi tak bertanda dan anda juga harus menyetel ulang pengaturan aplikasi.\n\nThanks! + + + Filter media + Gambar + Video + GIF + Gambar RAW + SVG + Tidak ada berkas media ditemukan dari filter ini. + Ubah filter + + + Fungsi ini menyembunyikan folder dengan menambahkan berkas \'.nomedia\' ke dalamnya, juga akan menyembunyikan semua subfolder. Anda bisa melihatnya dari opsi \'Tampilkan berkas tersembunyi\' di Pengaturan. Lanjutkan? + Kecualikan + Folder yang dikecualikan + Atur folder yang dikecualikan + Ini hanya akan mengecualikan pilihan bersama dengan subfoldernya di Simple Gallery. Anda bisa mengatur pengecualian di Pengaturan. + Kecualikan folder induk? + Mengecualikan folder akan membuatnya bersama subfoldernya tersembunyi hanya di Simple Gallery, namun masih bisa dilihat di aplikasi lain.\n\nJika anda ingin menyembunyikannya dari aplikasi lain juga, gunakan fitur Sembunyikan. + Bersihkan daftar + Hapus semua folder dari daftar pengecualian? Ini tidak akan menghapus folder tersebut. + Folder tersembunyi + Atur folder tersembunyi + Sepertinya tidak ada folder tersembunyi dengan berkas \".nomedia\" didalamnya. + + + Folder yang disertakan + Atur folder yang disertakan + Tambah folder + Jika ada folder yang berisi berkas media, namun tidak dikenali oleh aplikasi ini, anda bisa menambahkannya disini secara manual.\n\nMenambah beberapa item disini tidak akan mengecualikan folder yang lain. + Tidak ada berkas media yang ditemukan. Anda bisa memperbaikinya dengan menambahkan folder yang berisi berkas media secara manual. + + + Ubah ukuran + Ubah ukuran terpilih dan simpan + Lebar + Tinggi + Jaga aspek rasio + Harap masukkan resolusi dengan benar + + + Penyunting + Simpan + Rotasi + Jalur + Jalur gambar tidak valid + Gagal menyunting gambar + Sunting dengan: + Tidak ada aplikasi penyunting gambar + Lokasi berkas tidak diketahui + Tidak bisa mengganti berkas sumber + Putar ke kiri + Putar ke kanan + Putar 180º + Balik + Balik horizontal + Balik vertikal + Bebas + Lainnya + + + Simple Wallpaper + Setel wallpaper + Gagal menyetel sebagai wallpaper + Setel wallpaper dengan: + Menyetel wallpaper… + Wallpaper berhasil disetel + Aspek rasio potret + Aspek rasio lanskap + Layar beranda + Layar kunci + Beranda dan layar kunci + + + Slideshow + Interval (detik): + Sertakan foto + Sertakan video + Sertakan GIF + Urutan acak + Mundur + Slideshow tanpa henti + Animation + None + Fade + Slide + Slideshow berakhir + Tidak ditemukan media untuk slideshow + + + Ubah jenis tampilan + Kotak + Daftar + Kelompokkan subfolder langsung + + + Kelompokkan menurut + Jangan kelompokkan berkas + Folder + Terakhir diubah + Last modified (daily) + Last modified (monthly) + Tanggal diambil + Date taken (daily) + Date taken (monthly) + Jenis berkas + Ekstensi + Harap dicatat bahwa mengelompokkan dan mengurutkan adalah 2 ruas yang berbeda + + + Folder yang ditampilkan pada widget: + Tampilkan nama folder + + + Putar video otomatis + Ingat posisi pemutaran terakhir + Tampil/sembunyikan nama berkas + Ulangi video + Animasi GIF di thumbnail + Kecerahan maksimal saat melihat di layar penuh + Pangkas thumbnail menjadi persegi + Tampilkan durasi video + Rotasi layar penuh dari + Pengaturan sistem + Rotasi perangkat + Aspek rasio + Background dan status bar hitam saat layar penuh + Gulir thumbnail secara horizontal + Otomatis sembunyikan sistem UI saat layar penuh + Hapus folder kosong setelah menghapus isinya + Izinkan mengontrol kecerahan foto dengan gerakan vertikal + Izinkan mengontrol kecerahan dan volume video dengan gerakan vertikal + Tampilkan jumlah folder media di tampilan utama + Tampilkan detail tambahan saat layar penuh + Atur detail tambahan + Izinkan zoom satu jari di layar penuh + Izinkan mengganti media dengan mengklik sisi layar + Izinkan zoom gambar lebih dalam + Sembunyikan detail tambahan ketika status bar disembunyikan + Tampilkan beberapa tombol tindakan dibawah layar + Tampilkan Sampah di layar folder + Zoom gambar mendalam + Tampilkan gambar dalam kualitas tertinggi + Tampilkan Sampah sebagai item terakhir di layar utama + Izinkan keluar dari layar penuh dengan menggeser kebawah + Izinkan pembesaran 1:1 dengan dua kali ketuk + Selalu buka video pada layar terpisah dengan gestur horizontal baru + Tampilkan notch jika tersedia + Izinkan memutar gambar dengan gestur + Prioritas pemuatan berkas + Kecepatan + Kompromi + Hindari menampilkan berkas yang tidak valid + + + Thumbnail + Media layar penuh + Detail tambahan + Tindakan bawah + + + Sesuaikan tombol tindakan bawah + Favorit + Tampil/sembunyikan berkas + + + Bagaimana cara menjadikan Simple Gallery sebagai aplikasi galeri default? + Pertama anda harus menemukan galeri default saat ini di bagian Aplikasi di Pengaturan perangkat, lihatlah tombol yang seperti \"Buka secara default\", klik itu, lalu pilih \"Hapus default\". + Lain kali anda mencoba membuka gambar atau video, anda akan disuruh memilih aplikasi, dan anda bisa memilih Simple Gallery dan menjadikannya default. + Saya mengunci aplikasi dengan sandi, tapi saya lupa. Apa yang harus dilakukan? + Anda bisa menyelesaikannya dengan 2 cara. Anda bisa pasang ulang aplikasi, atau cari aplikasi ini di Pengaturan perangkat dan pilih \"Hapus data\". Ini akan menyetel ulang semua pengaturan anda, dan tidak akan menghapus berkas media apapun. + Bagaimana agar sebuah album selalu muncul paling atas di daftar? + Anda bisa menekan lama album tersebut dan pilih ikon Pin di menu tindakan, itu akan menaruhnya di atas daftar. Anda juga bisa menyematkan beberapa folder, item yang di-pin akan diurutkan berdasarkan metode urutan default. + Bagaimana cara mempercepat laju video? + You can either drag your finger horizontally over the video player, or click on the current or max duration texts near the seekbar. That will move the video either backward, or forward. + Apa perbedaan antara menyembunyikan dan mengecualikan folder? + Mengecualikan tidak akan menampilkan folder di Simple Gallery, sedangkan Sembunyikan bekerja sesuai aturan sistem dan akan menyembunyikan folder juga dari aplikasi galeri yang lain. Cara kerjanya dengan membuat berkas \".nomedia\" kosong pada folder yang diinginkan, yang bisa anda hapus juga dengan aplikasi pengelola berkas. + Mengapa folder dengan gambar album musik atau stiker muncul? + Kadang anda melihat beberapa album yang tidak biasa muncul. Anda bisa dengan mudah menyembunyikannya dengan menekan lama dan pilih Kecualikan. Pada dialog berikutnya, anda lalu bisa memilih folder induk, yang akan mencegah album terkait muncul kembali. + Ada folder berisi gambar namun tidak muncul, apa yang harus dilakukan? + Itu bisa disebabkan berbagai alasan, namun solusinya mudah. Pergi ke Pengaturan -> Atur folder yang disertakan, pilih Tambah dan cari folder yang diinginkan. + Bagaimana jika saya hanya ingin beberapa folder saja yang terlihat? + Menambahkan folder di Folder yang Disertakan tidak otomatis mengecualikan folder yang lain. Yang bisa anda lakukan adalah pergi ke Pengaturan -> Atur Folder yang Dikecualikan, lalu kecualikan folder root \"/\", lalu tambahkan folder yang diinginkan di Pengaturan -> Atur Folder yang Disertakan. + Itu akan membuat folder yang dipilih saja yang muncul, dan jika sebuah folder disertakan dan dikecualikan secara bersamaan, folder tersebut akan muncul. + Bisakah saya meng-crop gambar dengan aplikasi ini? + Ya, anda bisa melakukannya di Penyunting, dengan menyeret sudut gambar. Anda bisa masuk ke penyunting dengan menekan lama thumbnail gambar dan memilih Sunting, atau pilih Sunting dari tampilan layar penuh. + Bisakah saya mengelompokkan thumbnail berkas media? + Bisa, gunakan menu \"Kelompokkan menurut\" pada tampilan thumbnail. Anda bisa mengelompokkan berkas dengan berbagai kriteria, termasuk Tanggal Diambil. Jika anda menggunakan fungsi \"Tampilkan semua isi folder\", anda juga bisa mengelompokkan berdasarkan foldernya. + Tidak bisa mengurutkan berdasarkan Tanggal Diambil, bagaimana cara memperbaikinya? + Itu umumnya disebabkan karena berkas yang disalin dari tempat lain. Anda bisa memperbaikinya dengan memilih berkas thumbnail dan pilih \"Perbaiki Tanggal Diambil\". + Saya melihat beberapa pita warna pada gambar. Bagaimana saya meningkatkan kualitasnya? + Solusi saat ini untuk menampilkan gambar berfungsi dengan baik dalam sebagian besar kasus, namun jika anda ingin kualitas gambar yang lebih baik, anda bisa mengaktifkan \"Tampilkan gambar dalam kualitas tertinggi\" di pengaturan aplikasi, pada bagian \"Zoom gambar mendalam\". + Saya punya berkas/folder tersembunyi. Bagaimana cara memunculkannya? + Anda bisa memilih menu \"Tampilkan sementara berkas tersembunyi\" di layar utama, atau \"Tampilkan berkas tersembunyi\" di pengaturan aplikasi untuk menampilkannya. Jika anda tidak ingin menyembunyikannya, tekan lama dan pilih \"Jangan sembunyikan\". Folder disembunyikan dengan menambahkan berkas \".nomedia\" di dalamnya, anda bisa menghapus berkas tersebut dengan aplikasi pengelola berkas. + Kenapa aplikasi menggunakan sangat banyak ruang kosong? + Cache aplikasi bisa mencapai 250MB, ini untuk menjamin pemuatan gambar yang lebih cepat. Jika aplikasi menggunakan lebih banyak lagi ruang kosong, sangat memungkinkan anda memiliki item di dalam Keranjang Sampah. Berkas tersebut akan menambah ukuran aplikasi. Anda bisa mengosongkan Keranjang sampah dengan cara membukanya dan menghapus semua berkas, atau dari pengaturan aplikasi. Semua berkas di dalam keranjang sampah akan otomatis dihapus setelah 30 hari. + + + + Simple Gallery Pro: Pengelola & Penyunting Foto + + Galeri luring tanpa iklan. Kelola, sunting, pulihkan dan lindungi foto & video + + Simple Gallery Pro adalah aplikasi galeri luring yang sangat mudah diubahsuai. Mengelola & menyunting foto anda, memulihkan berkas yang terhapus dari keranjang sampah, melindungi & menyembunyikan berkas, dan menampilkan banyak format foto & video, diantaranya RAW, SVG dan masih banyak lainnya. + + Aplikasi sama sekali tidak berisi iklan dan tidak membutuhkan perizinan yang tidak perlu. Dan karena aplikasi juga tidak membutuhkan akses internet, privasi anda terlindungi. + + ------------------------------------------------- + SIMPLE GALLERY PRO – FEATURES + ------------------------------------------------- + + • Offline gallery with no ads or popups + • Simple gallery photo editor – crop, rotate, resize, draw, filters & more + • No internet access needed, giving you more privacy and security + • No unnecessary permissions required + • Quickly search images, videos & files + • Open & view many different photo and video types (RAW, SVG, panoramic etc) + • A variety of intuitive gestures to easily edit & organize files + • Lots of ways to filter, group & sort files + • Customize the appearance of Simple Gallery Pro + • Available in 32 languages + • Mark files as favorites for quick access + • Protect your photos & videos with a pattern, pin or fingerprint + • Use pin, pattern & fingerprint to protect the app launch or specific functions too + • Recover deleted photos & videos from the recycle bin + • Toggle visibility of files to hide photos & videos + • Create a customizable slideshow of your files + • View detailed information of your files (resolution, EXIF values etc) + • Simple Gallery Pro is open source + … and much much more! + + PHOTO GALLERY EDITOR + Simple Gallery Pro makes it easy to edit your pictures on the fly. Crop, flip, rotate and resize your pictures. If you’re feeling a little more creative you can add filters and draw on your pictures! + + SUPPORT FOR MANY FILE TYPES + Unlike some other gallery viewers & photo organizers, Simple Gallery Pro supports a huge range of different file types including JPEG, PNG, MP4, MKV, RAW, SVG, Panoramic photos, Panoramic videos and many more. + + HIGHLY CUSTOMIZABLE GALLERY MANAGER + From the UI to the function buttons on the bottom toolbar, Simple Gallery Pro is highly customizable and works the way you want it to. No other gallery manager has this kind of flexibility! Thanks to being open source, we’re also available in 32 languages! + + RECOVER DELETED PHOTOS & VIDEOS + Accidentally deleted a precious photo or video? Don’t worry! Simple Gallery Pro features a handy recycle bin where you can recover deleted photos & videos easily. + + PROTECT & HIDE PHOTOS, VIDEOS & FILES + Using pin, pattern or your device’s fingerprint scanner you can protect and hide photos, videos & entire albums. You can protect the app itself or place locks on specific functions of the app. For example, you can’t delete a file without a fingerprint scan, helping to protect your files from accidental deletion. + + Check out the full suite of Simple Tools here: + https://www.simplemobiletools.com + + Facebook: + https://www.facebook.com/simplemobiletools + + Reddit: + https://www.reddit.com/r/SimpleMobileTools + + + + diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 5728aed02..4ca5ac135 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -63,6 +63,7 @@ Gestisci le cartelle incluse Aggiungi cartella Se si hanno alcune cartelle che contengono media, ma non sono state riconosciute dall\'app, si possono aggiungerle manualmente qui. + No media files have been found. You can solve it by adding the folders containing media files manually. Ridimensiona @@ -112,12 +113,14 @@ Includi video Includi GIF Ordine sparso - Usa animazioni a dissolvenza Scorri al contrario Ripeti presentazione + Animation + None + Fade + Slide La presentazione è terminata Nessun file trovato per la presentazione - Usa le animazioni in dissolvenza Cambia modalità visualizzazione @@ -130,7 +133,11 @@ Non raggruppare i file Cartella Ultima modifica + Last modified (daily) + Last modified (monthly) Data creazione + Date taken (daily) + Date taken (monthly) Tipo di file Estensione Notare che il raggruppamento e l\'ordinamento sono due campi indipendenti diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 90ab09151..243c98235 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -63,6 +63,7 @@ 追加フォルダの管理 フォルダを追加 メディア入りのフォルダがアプリで認識されない場合は手動で追加します。 + No media files have been found. You can solve it by adding the folders containing media files manually. リサイズ @@ -112,12 +113,14 @@ ビデオを含める GIFを含める ランダムな順序 - フェードアニメーションを使用する 逆方向に進む スライドショーをリピート再生する + アニメーション + なし + フェード + スライド スライドショーが終了しました スライドショーに表示するメディアがありません - クロスフェードアニメーションを使用する 表示形式の変更 @@ -130,7 +133,11 @@ 何もしない フォルダ 更新日時 + 更新日時 (毎日) + 更新日時 (毎月) 撮影日時 + 撮影日時 (毎日) + 撮影日時 (毎月) ファイル形式 拡張子 Please note that grouping and sorting are 2 independent fields diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 6e3e2f342..d2362a199 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -63,6 +63,7 @@ 포함된 폴더 관리 폴더 추가 미디어가 포함되어 있지만 앱에서 인식하지 못하는 폴더가있는 경우 여기에서 수동으로 추가 할 수 있습니다. \n\n여기에 항목을 추가해도 원본 폴더에서 제외되지 않습니다. + No media files have been found. You can solve it by adding the folders containing media files manually. 크기 변경 @@ -112,12 +113,14 @@ 포함된 비디오 포함된 GIFs 랜덤 순서 - 페이드 애니메이션 사용 뒤로 이동 슬라이드 쇼 반복 + Animation + None + Fade + Slide 슬라이드 쇼 종료 슬라이드 쇼를 위한 미디어를 찾을 수 없음 - Use crossfade animations 보기방식 변경 @@ -130,7 +133,11 @@ Do not group files Folder Last modified + Last modified (daily) + Last modified (monthly) Date taken + Date taken (daily) + Date taken (monthly) File type Extension Please note that grouping and sorting are 2 independent fields diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 22444b047..564b12e21 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -63,6 +63,7 @@ Tvarkyti įtrauktus aplankus Įtraukti aplanką Jei turite tam tikrų aplankų, kuriuose yra medijos , bet kurių neneatpažįsta programėlė, galite juos pridėti rankiniu būdu. \ N \ nPridedant kai kuriuos elementus, neišskirsite jokio kito aplanko. + No media files have been found. You can solve it by adding the folders containing media files manually. Keisti dydį @@ -112,12 +113,14 @@ Įtraukti vaizdo įrašus Itraukti GIF\'us Atsitiktinė tvarka - Naudoti išblukimo animacijas Sukti atgal Klipuoti skaidrių demonstraciją + Animation + None + Fade + Slide Skaidrių demonstracija pasibaigė Nerasta medijos skaidrių demonstracijai - Use crossfade animations Keisti peržiūros tipą @@ -130,7 +133,11 @@ Do not group files Folder Last modified + Last modified (daily) + Last modified (monthly) Date taken + Date taken (daily) + Date taken (monthly) File type Extension Please note that grouping and sorting are 2 independent fields diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index ef7d0707a..998c2dcb3 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -63,6 +63,7 @@ Håndter inkluderte mapper Legg til mappe Hvis du har noen mapper som inneholder media, men ikke ble gjenkjent av appen, kan du legge dem til manuelt her.\n\nÅ legge til noen elementer her, ekskluderer ikke noen annen mappe. + Ingen mediafiler er funnet. Dette kan løses ved å legge til mapper som inneholder mediafiler manuelt. Endre størrelse @@ -112,12 +113,14 @@ Inkluder videoer Inkluder GIF-bilder Tilfeldig rekkefølge - Bruk toningseffekt Avspill bakover Gjenta lysbildeshow + Animasjon + Ingen + Fade + Slide Lysbildeshowet er slutt Ingen media for lysbildeshowet er funnet - Bruk krysstoningsanimasjon Endre visningstype @@ -130,7 +133,11 @@ Ikke grupper filer Mappe Sist endret + Sist endret (daglig) + Sist endret (månedlig) Dato tatt + Dato tatt (daglig) + Dato tatt (månedlig) Filtype Endelse Vær oppmerksom på at gruppering og sortering er to uavhengige områder diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 29ff119f5..f84455f71 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -63,6 +63,7 @@ Toegevoegde mappen beheren Map toevoegen Als er mappen zijn die wel media bevatten, maar niet door de galerij worden herkend, voeg deze mappen dan hier handmatig toe.\n\nHet hier toevoegen van mappen zal andere mappen niet uitsluiten. + Er zijn geen mediabestanden gevonden. Dit kan worden opgelost door de mappen met mediabestanden handmatig toe te voegen. Grootte aanpassen @@ -112,12 +113,14 @@ Video’s weergeven GIF-bestanden weergeven Willekeurige volgorde - Animaties gebruiken (vervagen) Omgekeerde volgorde Voorstelling herhalen + Overgangseffect + Geen + Overvloeien + Verschuiven De diavoorstelling is beëindigd Geen media gevonden voor diavoorstelling - Crossfade-animaties gebruiken Weergave @@ -130,7 +133,11 @@ Bestanden niet groeperen Map Laatst gewijzigd + Laatst gewijzigd (per dag) + Laatst gewijzigd (per maand) Datum opname + Datum opname (per dag) + Datum opname (per maand) Bestandstype Extensie Groeperen en sorteren zijn twee aparte opties diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index b7edb9672..721e90ec2 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -1,14 +1,14 @@ Prosta Galeria -    Galeria + Galeria Edytuj Uruchom aplikację aparatu (ukryty) (wykluczony) Przypnij folder Odepnij folder -    Przypnij na górze + Przypnij na górze Pokaż wszystko Wszystkie foldery Przełącz na widok folderów @@ -51,11 +51,11 @@ Zarządzaj wykluczonymi folderami Działa na folderach galerii. Możesz zarządzać wykluczonymi folderami w ustawieniach aplikacji. Wykluczyć folder nadrzędny? -    Wykluczenie folderów ukryje je tylko w niniejszej aplikacji, w innych aplikacjach będą one wciąż widoczne.\n\nJeśli chcesz je ukryć także w innych aplikacjach, użyj funkcji ukrywania. + Wykluczenie folderów ukryje je tylko w niniejszej aplikacji, w innych aplikacjach będą one wciąż widoczne.\n\nJeśli chcesz je ukryć także w innych aplikacjach, użyj funkcji ukrywania. Usuń wszystko Usunąć wszystkie foldery z listy wykluczonych? Foldery nie zostaną fizycznie usunięte. Ukryte foldery -    Zarządzaj ukrytymi folderami + Zarządzaj ukrytymi folderami Zdaje się, że nie masz żadnych folderów z plikiem \'.nomedia\'. @@ -63,6 +63,7 @@ Zarządzaj dołączonymi folderami Dodaj folder Jeśli masz jakieś foldery z multimediami, ale aplikacja ich nie wykryła, możesz je dodać ręcznie tutaj. + No media files have been found. You can solve it by adding the folders containing media files manually. Zmień rozmiar @@ -70,7 +71,7 @@ Szerokość Wysokość Zachowaj proporcje -    Podaj poprawną rozdzielczość + Podaj poprawną rozdzielczość Edycja @@ -101,9 +102,9 @@ Tapeta została ustawiona Proporcje ekranu w trybie pionowym Proporcje ekranu w trybie poziomym -    Pulpit -    Ekran blokady -    Pulpit i ekran blokady + Pulpit + Ekran blokady + Pulpit i ekran blokady Pokaz slajdów @@ -112,17 +113,19 @@ Dołączaj filmy Dołączaj GIFy Losowa kolejność - Używaj płynnych przejść -    Odwrotna kolejność -    Zapętlaj + Odwrotna kolejność + Zapętlaj + Animation + None + Fade + Slide Pokaz slajdów zakończony Nie znalazłem multimediów do pokazu slajdów - Używaj animacji przejścia -    Zmień typ widoku -    Siatka -    Lista + Zmień typ widoku + Siatka + Lista Grupuj bezpośrednie podfoldery @@ -130,7 +133,11 @@ Nie grupuj plików Folderu Daty ostatniej modyfikacji + Last modified (daily) + Last modified (monthly) Daty utworzenia + Date taken (daily) + Date taken (monthly) Typu Rozszerzenia Uwaga: grupowanie i sortowanie to dwa niezależne pola @@ -152,21 +159,19 @@ Ustawień systemowych Orientacji urządzenia Proporcji -    Czarne tło i pasek stanu przy widoku pełnoekranowym + Czarne tło i pasek stanu przy widoku pełnoekranowym Przewijaj miniatury poziomo Ukrywaj interfejs przy pełnoekranowym podglądzie Usuwaj puste foldery po usunięciu ich zawartości -    Zezwalaj na kontrolowanie jasności zdjęcia pionowymi gestami -    Zezwalaj na kontrolowanie jasności i głośności filmów pionowymi gestami + Zezwalaj na kontrolowanie jasności zdjęcia pionowymi gestami + Zezwalaj na kontrolowanie jasności i głośności filmów pionowymi gestami Pokazuj liczbę elementów w folderach w głównym widoku Dodatkowe szczegóły przy podglądzie pełnoekranowym Zarządzaj dodatkowymi szczegółami -    Zezwalaj na powiększanie jednym palcem w widoku pełnoekranowym -    Zezwalaj na natychmiastową zmianę multimediów po kliknięciu boków ekranu + Zezwalaj na powiększanie jednym palcem w widoku pełnoekranowym + Zezwalaj na natychmiastową zmianę multimediów po kliknięciu boków ekranu Zezwalaj na duże powiększanie obrazów - Ukrywaj dodatkowe szczegóły, gdy pasek stanu jest ukryty + Ukrywaj dodatkowe szczegóły, gdy pasek stanu jest ukryty Pokazuj niektóre przyciski akcji na dole ekranu Pokazuj kosz w widoku folderów Duże powiększanie obrazów @@ -183,9 +188,9 @@ Unikaj pokazywania niewłaściwych plików -    Miniatury -    Widok pełnoekranowy -    Dodatkowe szczegóły + Miniatury + Widok pełnoekranowy + Dodatkowe szczegóły Przyciski na dolnym pasku @@ -194,22 +199,22 @@ Widoczność plików -    Jak mogę ustawić tą aplikację jako domyślną aplikację galerii? -    Znajdź obecną domyślną aplikację galerii w ustawieniach systemowych (sekcja \'Aplikacje\'). Na ekranie z informacjami o niej kliknij \'Otwórz domyślnie\', a następnie \'Wyczyść domyślne\'. Gdy podczas następnej próby otwarcia zdjęcia czy filmu system zapyta Cię jaką aplikacją to zrobić, wybierz Prostą Galerię i opcję zapamiętania tego wyboru. -    Zablokowałem(-am) aplikację hasłem i wyleciało mi ono z głowy. Co mogę zrobić? -    Masz dwie opcje: przeinstalowanie aplikacji lub wyczyszczenie jej ustawień. Niezależnie od wyboru, pliki pozostaną nienaruszone. -    Jak sprawić, aby album(y) zawsze pojawiał(y) się na górze? -    Przytrzymaj album(y) i wybierz ikonę przypięcia w pasku akcji. -    Jak mogę przwijać filmy? + Jak mogę ustawić tą aplikację jako domyślną aplikację galerii? + Znajdź obecną domyślną aplikację galerii w ustawieniach systemowych (sekcja \'Aplikacje\'). Na ekranie z informacjami o niej kliknij \'Otwórz domyślnie\', a następnie \'Wyczyść domyślne\'. Gdy podczas następnej próby otwarcia zdjęcia czy filmu system zapyta Cię jaką aplikacją to zrobić, wybierz Prostą Galerię i opcję zapamiętania tego wyboru. + Zablokowałem(-am) aplikację hasłem i wyleciało mi ono z głowy. Co mogę zrobić? + Masz dwie opcje: przeinstalowanie aplikacji lub wyczyszczenie jej ustawień. Niezależnie od wyboru, pliki pozostaną nienaruszone. + Jak sprawić, aby album(y) zawsze pojawiał(y) się na górze? + Przytrzymaj album(y) i wybierz ikonę przypięcia w pasku akcji. + Jak mogę przwijać filmy? Na dwa sposoby: albo przeciągając poziomo palcem po filmie, albo klikając obecny (przewinięcie do tyłu) lub całkowity czas trwania (do przodu). -    Jaka jest różnica między ukryciem, a wykluczeniem folderu? -    Wykluczenie działa tylko w obrębie niniejszej aplikacji (wszędzie indziej pliki są normalnie widoczne), ukrywanie - w obrębie całego systemu (nie widać ich nigdzie), dodawany jest wtedy do folderu pusty plik \'.nomedia\', który możesz usunąć w dowolnym menedżerze plików. -    Dlaczego pokazują mi się foldery z okładkami do piosenek i tym podobne rzeczy? + Jaka jest różnica między ukryciem, a wykluczeniem folderu? + Wykluczenie działa tylko w obrębie niniejszej aplikacji (wszędzie indziej pliki są normalnie widoczne), ukrywanie - w obrębie całego systemu (nie widać ich nigdzie), dodawany jest wtedy do folderu pusty plik \'.nomedia\', który możesz usunąć w dowolnym menedżerze plików. + Dlaczego pokazują mi się foldery z okładkami do piosenek i tym podobne rzeczy? Aplikacja nie wie, czy dany obraz jest okładką od piosenki czy czymś innym. Aby ukryć niechciane rzeczy, przytrzymaj je i wybierz opcję \'Wyklucz\' z paska akcji. -    Nie pokazuje(-ą) mi się folder(y) ze zdjęciami / filmami. Co mogę zrobić? -    Wejdź do ustawień aplikacji i w sekcji z dołączonymi folderami dodaj tenże folder do listy. + Nie pokazuje(-ą) mi się folder(y) ze zdjęciami / filmami. Co mogę zrobić? + Wejdź do ustawień aplikacji i w sekcji z dołączonymi folderami dodaj tenże folder do listy. Co jeśli chcę widzieć tylko wybrane foldery? -    Przejdź do sekcji z wykluczonymi folderami w ustawieniach aplikacji, dodaj tam folder główny (\"/\"), a następnie dodaj pożądane foldery w sekcji z dołączonymi folderami. + Przejdź do sekcji z wykluczonymi folderami w ustawieniach aplikacji, dodaj tam folder główny (\"/\"), a następnie dodaj pożądane foldery w sekcji z dołączonymi folderami. Czy mogę w tej aplikacji przycinać obrazy? Tak, możesz to zrobić w edytorze, przeciągając krawędzie obrazu. Edytor otworzysz przytrzymując miniaturę obrazu i wybierając opcję \'Edytuj\', bądź wybierając tą samą opcję w menu pełnoekranowym. Czy mogę jakoś grupować miniatury plików? diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index fc60450b6..970fe03ad 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1,13 +1,13 @@ - Simple Gallery + Simple Galeria Galeria Editar Abrir câmera (oculto) (excluído) Fixar pasta - Desfixar pasta + Desafixar pasta Fixar no topo Mostrar conteúdo de todas as pastas Todas as pastas @@ -24,45 +24,46 @@ Brilho Travar orientação Destravar orientação - Mudar orientação + Alterar orientação Forçar modo retrato Forçar modo paisagem Usar orientação padrão - Fix Date Taken value - Fixing… - Dates fixed successfully - Share a resized version - Hey,\n\nparece que você atualizou o antigo aplicativo gratuito. Agora você poderá desinstalar a velha versão que tem o botão \'Atualize para a versão Pro\' no topo das Configurações.\n\nVocê terá os itens da Lixeira excluídos, itens favoritos desmarcados e também terá que redefinir as configurações do seu aplicativo.\n\nObrigado! + Corrigir data da foto + Corrigindo… + Datas corrigidas com sucesso + Compartilhar uma versão redimensionada + Olá,\n\nparece que você atualizou o antigo aplicativo gratuito. Agora você poderá desinstalar a velha versão que tem o botão de atualizar para a versão Pro no topo das Configurações.\n\nVocê terá os itens da Lixeira excluídos, itens favoritos desmarcados e também terá que redefinir as configurações do seu aplicativo.\n\nObrigado! Filtrar mídia Imagens Vídeos GIFs - RAW images + Imagens RAW SVGs Nenhum arquivo de mídia encontrado a partir dos filtros selecionados. - Mudar filtros + Alterar filtros - Esta opção oculta uma pasta com a adição de um arquivo \'.nomedia\' dentro dela, e irá ocultar todas as subpastas que estejam dentro da mesma. Você poderá rever essas pastas com a opção \'Mostrar pastas ocultas\'. Continuar? - Excluir - Pastas excluídas - Gerenciar pastas excluídas - Esta ação irá excluir as pastas selecionadas apenas dentro deste aplicativo. Você pode gerenciar as pastas excuídas nas Configurações do aplicativo. - Excluir antes a pasta raiz? - A exclusão de uma pasta apenas oculta o seu conteúdo da galeria, pois todos os outros aplicativos poderão acessá-las.\\n\\nSe quiser ocultar de todos os aplicativos, utilize a função ocultar. + Esta opção oculta a pasta com a adição de um arquivo \".nomedia\" dentro dela, o que também ocultará todas as subpastas que estejam dentro da mesma. Você poderá voltar a exibir estas pastas com a opção \"Mostrar pastas ocultas\". Continuar? + Ignorar + Pastas ignoradas + Gerenciar pastas ignoradas + Esta ação deixará de exibir as pastas selecionadas apenas dentro deste aplicativo. Você pode gerenciar as pastas ignoradas nas Configurações do aplicativo. + Ignorar a pasta raiz ao invés desta? + Ignorar uma pasta apenas deixa de exibi-la nesta galeria. Ela continuará visível para outros aplicativos.\\n\\nSe você quiser ocultar a pasta para todos os aplicativos, utilize a função ocultar. Remover todas - Remover todas as pastas da lista de exclusões? Esta ação não apaga as pastas. + Remover todas as pastas da lista de pastas ignoradas? Esta ação não exclui as pastas. Pastas ocultas Gerenciar pastas ocultas - Parece que você não tem nenhuma pasta oculta com um arquivo \".nomedia\". + Parece que você não tem nenhuma pasta ocultada por um arquivo \".nomedia\". Pastas incluídas Gerenciar pastas incluídas Adicionar pasta - Se possuir pastas com dados multimídia não reconhecidos pelo aplicativo, aqui você pode adicioná-las manualmente. + Se você possuir pastas com dados multimídia não reconhecidos pelo aplicativo, aqui você pode adicioná-las manualmente. + Nenhum arquivo de mídia foi encontrado. Como alternativa você pode tentar incluir manualmente as pastas com arquivos de mídia. Redimensionar @@ -89,16 +90,16 @@ Inverter Horizontalmente Verticalmente - Gratuito + Livre Outro - Simple Wallpaper + Simple Papel de Parede Definir como papel de parede Falha ao definir como papel de parede Definir papel de parede com: Definindo como papel de parede - Papel de parede com sucesso + Papel de parede definido com sucesso Retrato Paisagem Tela inicial @@ -109,34 +110,40 @@ Apresentação Intervalo (segundos): Incluir fotos - Incluir videos + Incluir vídeos Incluir GIFs Ordem aleatória - Usar animação de esmaecimento Retroceder Apresentação em ciclo + Animação + Nenhuma + Esmaecer + Deslizar Fim da apresentação Nenhuma mídia encontrada para a apresentação - Usar animações crossfade Alterar modo de visualização Grade Lista - Agrupar subpastas do diretório + Agrupar subpastas diretas Agrupar por Não agrupar arquivos Pasta Última modificação - Data de criação + Última modificação (por dia) + Última modificação (por mês) + Data da foto + Data da foto (por dia) + Data da foto (por mês) Tipo de arquivo Extensão - Por favor, note que o agrupamento e classificação são 2 campos independentes + Por favor, lembre-se que o agrupamento e classificação são configurados por dois campos independentes - Exibição da Pasta no widget: + Pasta exibida no widget: Exibir nome da pasta @@ -144,135 +151,132 @@ Lembrar da última posição de reprodução de vídeo Mostrar/ocultar nome do arquivo Reproduzir vídeos em ciclo - Animação de GIFs nas miniaturas - Brilho máximo ao visualizar mídia + Animar GIFs nas miniaturas + Maximizar o brilho ao visualizar mídia em tela cheia Recortar miniaturas em quadrados - Exibir durações de vídeo + Exibir duração dos vídeos Critério para rotação de tela Padrão do sistema Sensor do aparelho Proporção da mídia Fundo de tela e barra de status preta quando em visualização de tela cheia Rolar miniaturas horizontalmente - Esconder interface do sistema automaticamente quando em tela cheia - Apagar pastas vazias após deleter seu conteúdo + Esconder interface do sistema quando em tela cheia + Apagar pastas vazias após excluir o seu conteúdo Permitir controle do brilho com gestos na vertical Permitir controle do volume e brilho com gestos na vertical - Mostrar quantidade de arquivos das pastas - Exibir detalhes extendidos quando em tela cheia - Gerenciar detalhes extendidos + Mostrar quantidade de arquivos em cada pasta na tela inicial + Exibir detalhes adicionais quando em tela cheia + Gerenciar detalhes adicionais Permitir zoom com um dedo quando em exibição de tela cheia - Permitir alternância instantânia de mídia clicando nas laterais da tela - Permitir zoom aprofundado em imagens - Ocultar detalhes extendidos quando a barra de status estiver oculta + Tocar na lateral da tela navega para a próxima imagem ou vídeo + Permitir zoom aprofundado para imagens + Ocultar detalhes adicionais quando a barra de status estiver oculta Mostrar alguns botões de ação na parte inferior da tela - Mostar a Lixeira na tela de pastas - Imagens com zoom aprofundado - Mostrar imagens com a maior qualidade possível - Mostrar a Lixeira como o último item na tela principal - Permitir fechar a exibição em tela cheia com um gesto para baixo - Permitir zoom 1:1 com dois toques duplos + Mostrar a Lixeira na tela inicial + Zoom aprofundado para imagens + Mostrar imagens na maior qualidade possível + Mostrar a Lixeira como o último item na tela inicial + Gesto para baixo sai da exibição em tela cheia + Dois toques duplos fazem zoom 1:1 Sempre abrir vídeos em uma tela separada com novos gestos horizontais - Mostrar um encaixe, se disponível + Mostrar o notch, se existente Permitir rotação de imagens com gestos Prioridade de carregamento de arquivos Velocidade - Compromise - Evite exibit arquivos inválidos + Meio termo + Evitar a exibição de arquivos inválidos Miniaturas Mídia em tela cheia - Detalhes extendidos - Bottom actions + Detalhes adicionais + Botões de ação - Manage visible bottom actions - Toggle favorite - Toggle file visibilityv + Gerenciar botões de ação + Favoritar/Desfavoritar + Exibir/Ocultar arquivov - Como eu posso tornar o Simple Gallery como galeria padrão do meu aparelho? - First you have to find the currently default gallery in the Apps section of your device settings, look for a button that says something like \"Open by default\", click on it, then select \"Clear defaults\". - The next time you will try opening an image or video you should see an app picker, where you can select Simple Gallery and make it the default app. - I locked the app with a password, but I forgot it. What can I do? - You can solve it in 2 ways. You can either reinstall the app, or find the app in your device settings and select \"Clear data\". It will reset all your settings, it will not remove any media files. - How can I make an album always appear at the top? - You can long press the desired album and select the Pin icon at the actions menu, that will pin it to the top. You can pin multiple folders too, pinned items will be sorted by the default sorting method. - How can I fast-forward videos? - You can either drag your finger horizontally over the video player, or click on the current or max duration texts near the seekbar. That will move the video either backward, or forward. - What is the difference between hiding and excluding a folder? - Exclude prevents displaying the folder only in Simple Gallery, while Hide works system-wise and it hides the folder from other galleries too. It works by creating an empty \".nomedia\" file in the given folder, which you can then remove with any file manager too. - Why do folders with music cover art or stickers show up? - It can happen that you will see some unusual albums show up. You can easily exclude them by long pressing them and selecting Exclude. In the next dialog you can then select the parent folder, chances are it will prevent the other related albums showing up too. - A folder with images isn\'t showing up, or it doesn\'t show all items. What can I do? - That can have multiple reasons, but solving it is easy. Just go in Settings -> Manage Included Folders, select Plus and navigate to the required folder. - What if I want just a few particular folders visible? - Adding a folder at the Included Folders doesn\'t automatically exclude anything. What you can do is go in Settings -> Manage Excluded Folders, exclude the root folder \"/\", then add the desired folders at Settings -> Manage Included Folders. - That will make only the selected folders visible, as both excluding and including are recursive and if a folder is both excluded and included, it will show up. - Can I crop images with this app? - Yes, you can crop images in the editor, by dragging the image corners. You can get to the editor either by long pressing an image thumbnail and selecting Edit, or selecting Edit from the fullscreen view. - Can I somehow group media file thumbnails? - Sure, just use the \"Group by\" menu item while at the thumbnails view. You can group files by multiple criteria, including Date Taken. If you use the \"Show all folders content\" function you can group them by folders too. - Sorting by Date Taken doesn\'t seem to work properly, how can I fix it? - It is most likely caused by the files being copied from somewhere. You can fix it by selecting the file thumbnails and selecting \"Fix Date Taken value\". - I see some color banding on the images. How can I improve the quality? - The current solution for displaying images works fine in the vast majority of cases, but if you want even better image quality, you can enable the \"Show images in the highest possible quality\" at the app settings, in the \"Deep zoomable images\" section. + O que devo fazer para que a Simple Galeria seja o aplicativo de galeria padrão do meu aparelho? + Primeiro, você deve encontrar o aplicativo padrão atual nas configurações do seu aparelho, e apertar o botão que diz "Limpar Padrões". + Na próxima vez que você abrir uma imagem ou vídeo, você deverá ver um seletor do aplicativo, no qual você terá a oportunidade de selecionar a Simple Galeria como o app padrão. + Eu protegi o app com senha, mas me esqueci da senha. O que posso fazer? + Você pode resolver isto de duas formas. A primeira é reinstalar o aplicativo. A segunda é ir nas configurações do seu dispositivo e selecionar a opção "Restaurar preferências do app". + Como posso fazer para que uma pasta sempre apareça no topo da lista? + Faça um toque longo na pasta em questão, e depois toque no ícone de alfinete na parte superior da tela para fixar a pasta ao topo. Se você fixar múltiplas pastas, elas serão ordenadas de acordo como seu critério de ordenação padrão. + Como faço para avançar rapidamente um vídeo (fast-forward)? + Você pode fazer um gesto horizontal como dedo, ou tocar nos números de tempo atual ou tempo total do vídeo, que se encontram próximos à barra de posicionamento. + Qual é a diferença entre ocultar e ignorar uma pasta? + O opção de ignorar deixa de exibir a pasta apenas na Simple Galeria, enquanto a opção de ocultar afeta todo o sistema, e também irá deixar de exibir a pasta em outros apps de galeria. A função de ocultar cria um arquivo vazio chamado \".nomedia\" na raiz da pasta em questão. Caso você queira fazer a pasta voltar a ser exibida, você pode excluir o arquivo \".nomedia\" usando o gerenciador de arquivos. + Porque pastas com capas de CD de música ou figurinhas aparecem na lista? + Você pode pedir para a Simple Galeria ignorar estas pastas, adicionando a pasta raiz onde você guarda as suas músicas à lista de pastas ignoradas. Uma maneira de fazer isso é fazer um toque longo em uma destas pastas, e selecionar a opção Ignorar e, em seguida, seleciona a pasta pai. + Uma das minhas pastas não aparece, ou nem todos os seus itens são exibidos. O que posso fazer? + Isso pode ocorrer por diversos motivos, mas resolver o problema é fácil. Entre em Configurações --> Gerenciar pastas incluídas, toque no botão \"+\", e selecione a pasta em questão. + Como posso fazer para exibir apenas certas pastas? + Adicionar uma pasta à lista de Pastas Incluídas não remove outras pastas da exibição. O que você pode fazer é ir em Configurações -> Gerenciar pastas ignoradas, excluir a pasta raiz \"/\", e finalmente incluir somente as pastas desejadas através de Configurações -> Gerenciar pastas incluídas. + Posso recortar imagens usando este app? + Sim, você pode recortar imagens no editor, arrastando os cantos da imagem. Você pode entrar no editor fazendo um toque longo na imagem e selecionando Editar, ou selecionando Editar a partir da visualização de tela cheia. + É possível exibir os meus arquivos de mídia em subgrupos ao invés de em uma única grande lista? + Você pode usar a opção \"Agrupar por\" para agrupar os seus arquivos de mídia por data, formato ou outros critérios. Se a opção \"Mostrar conteúdo de todas as pastas\" estiver ativada, você também poderá agrupar por subpasta. + A ordenação por Data da Foto não funciona corretamente. O que posso fazer? + Isto pode ter ocorrer caso as suas fotos tenham sido copiadas de outro local. Para resolver o problema, você pode selecionar a função \"Corrigir data da foto\" no menu deste aplicativo. + Algumas imagens exibem artefatos de exibição, como bandas de cor. Como posso melhorar a qualidade da exibição? + O nosso método atual para a exibição de imagens funciona bem na grande maioria dos casos, mas caso você queira uma qualidade ainda melhor, ative a opção \"Mostrar imagens na maior qualidade possível\" na seção \"Zoom aprofundado para imagens\" das configurações deste aplicativo. I have hidden a file/folder. How can I unhide it? You can either press the \"Temporarily show hidden items\" menu item at the main screen, or toggle \"Show hidden items\" in the app settings to see the hidden item. If you want to unhide it, just long press it and select \"Unhide\". Folders are hidden by adding a hidden \".nomedia\" file into them, you can delete the file with any file manager too. - Why does the app take up so much space? - App cache can take up to 250MB, it ensures quicker image loading. If the app is taking up even more space, it is most likely caused by you having items in the Recycle Bin. Those files count to the app size. You can clear the Recycle bin by opening it and deleting all files, or from the app settings. Every file in the Bin is deleted automatically after 30 days. + Porque este app gasta tanto espaço? + O cache deste app, que garante que as imagens sejam carregadas mais rapidamente, pode gastar até 250 MB. Se o app estiver gastando mais espaço que isso, pode ser por que você tem muitos arquivos na sua Lixeira. Arquivos na Lixeira são removidos permanentemente após 30 dias, mas se sua Lixeira estiver usando muito espaço apesar disso você pode esvaziá-la manualmente. Para fazer isso, você pode abrir a Lixeira e excluir os arquivos dentro dela, ou você pode fazer o mesmo na tela de configurações deste app. - Simple Gallery Pro: Photo Manager & Editor + Simple Galeria Pro: Gerenciador de Imagens - Offline gallery without ads. Organize, edit, recover and protect photos & videos + Galeria offline sem anúncios. Organize, edite, e proteja fotos e vídeos. - Simple Gallery Pro is a highly customizable offline gallery. Organize & edit your photos, recover deleted files with the recycle bin, protect & hide files and view a huge variety of different photo & video formats including RAW, SVG and much more. - - The app contains no ads and unnecessary permissions. As the app doesn’t require internet access either, your privacy is protected. + A Simple Galeria Pro é uma galeria de imagens e vídeos altamente customizável. Organize e edite suas fotos e vídeos, recupere arquivos movidos para a lixeira, proteja e oculte seus arquivos, e visualize arquivos em uma grande variedade de formatos, incluindo RAW, SVG, e muito mais. + Este app não inclui anúncios ou permissões desnecessárias e também não acessa a internet. Sua privacidade está protegida. ------------------------------------------------- - SIMPLE GALLERY PRO – FEATURES + SIMPLE GALERIA PRO – FUNCIONALIDADES ------------------------------------------------- - • Offline gallery with no ads or popups - • Simple gallery photo editor – crop, rotate, resize, draw, filters & more - • No internet access needed, giving you more privacy and security - • No unnecessary permissions required - • Quickly search images, videos & files - • Open & view many different photo and video types (RAW, SVG, panoramic etc) - • A variety of intuitive gestures to easily edit & organize files - • Lots of ways to filter, group & sort files - • Customize the appearance of Simple Gallery Pro - • Available in 32 languages - • Mark files as favorites for quick access - • Protect your photos & videos with a pattern, pin or fingerprint - • Use pin, pattern & fingerprint to protect the app launch or specific functions too - • Recover deleted photos & videos from the recycle bin - • Toggle visibility of files to hide photos & videos - • Create a customizable slideshow of your files - • View detailed information of your files (resolution, EXIF values etc) - • Simple Gallery Pro is open source - … and much much more! + • Galeria offline sem anúncios ou popups + • Editor de imagens – recorte, rotacione, redimensione, desenhe, adicione filtros, e muito mais + • Não requer acesso à internet. Mais privacidade e segurança. + • Não pede permissões desnecessárias + • Pesquise por imagens, vídeos e arquivos rapidamente + • Visualize diversos formatos de arquivos de imagem ou vídeo (RAW, SVG, imagens panorâmicas, etc) + • Use uma variedade de gestos intuitivos para editar e organizar seus arquivos + • Varias maneiras de filtrar, agrupar, e ordenar seus arquivos + • Customize a aparência da Simple Galeria Pro + • Disponível em 32 idiomas + • Marque seus arquivos favoritos para acesso mais rápido + • Proteja suas imagens e vídeos com um padrão, PIN, ou impressão digital + • Recupere imagens e vídeos que foram excluídos para a lixeira + • Oculte arquivos para deixar de exibir certas imagens ou vídeos no app. + • Crie um slideshow customizado com os seus arquivos + • Exiba informações avançadas sobre seus arquivos (resolução, metadados EXIF, etc) + • A Simple Galeria Pro tem código aberto! + … e muito mais! - PHOTO GALLERY EDITOR - Simple Gallery Pro makes it easy to edit your pictures on the fly. Crop, flip, rotate and resize your pictures. If you’re feeling a little more creative you can add filters and draw on your pictures! + EDITOR DE IMAGENS + Com a Simple Galeria Pro é bem fácil editar suas imagens na hora. Recorte, rotacione, e redimensione suas imagens. Se você estiver se sentindo mais criativo, você também pode desenhar ou adicionar filtros! - SUPPORT FOR MANY FILE TYPES - Unlike some other gallery viewers & photo organizers, Simple Gallery Pro supports a huge range of different file types including JPEG, PNG, MP4, MKV, RAW, SVG, Panoramic photos, Panoramic videos and many more. + SUPORTE A VÁRIOS FORMATOS DE ARQUIVO + Ao contrário de alguns outros aplicativos de organização de imagens, a Simple Galeria Pro é capaz de exibir uma grande variedade de formatos de arquivo, incluindo JPEG, PNG, MP4, MKV, RAW, SVG, fotos panorâmicas, vídeos panorâmicos e muito mais. - HIGHLY CUSTOMIZABLE GALLERY MANAGER - From the UI to the function buttons on the bottom toolbar, Simple Gallery Pro is highly customizable and works the way you want it to. No other gallery manager has this kind of flexibility! Thanks to being open source, we’re also available in 32 languages! + GERENCIADOR DE IMAGENS ALTAMENTE CUSTOMIZÁVEL + Desde a interface de usuário, até os botões da barra de ferramentas, a Simple Galeria Pro é altamente customizável, e você pode fazer com que ela funcione exatamente do seu jeito. Nenhum outro app de galeria de imagens é tão flexível! Além disso, por ter o código aberto, a Simple Galeria está disponível em 32 idiomas! - RECOVER DELETED PHOTOS & VIDEOS - Accidentally deleted a precious photo or video? Don’t worry! Simple Gallery Pro features a handy recycle bin where you can recover deleted photos & videos easily. + RECUPERE IMAGENS E VÍDEOS EXCLUÍDOS + Acidentalmente excluiu uma preciosa imagem ou vídeo? Não se preocupe! A Simple Galeria Pro vem com uma lixeira que permite facilmente recuperar fotos ou vídeos excluídos nos últimos 30 dias. + + PROTEJA E OCULTE FOTOS, VÍDEOS E ARQUIVOS + Usando um PIN, padrão, ou sua impressão digital, você pode proteger ou ocultar imagens, vídeos ou até álbuns inteiros. Você também pode proteger o app como um todo por senha, ou apenas funções específicas. Por exemplo, você pode fazer com que a Simple Galeria verifique a impressão digital antes de excluir arquivos, para ajudar a evitar que arquivos sejam excluí. - PROTECT & HIDE PHOTOS, VIDEOS & FILES - Using pin, pattern or your device’s fingerprint scanner you can protect and hide photos, videos & entire albums. You can protect the app itself or place locks on specific functions of the app. For example, you can’t delete a file without a fingerprint scan, helping to protect your files from accidental deletion. - - Check out the full suite of Simple Tools here: + Dê uma olhada nos nossos outros aplicativos Simple: https://www.simplemobiletools.com Facebook: diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index e878df4c2..6a44570d5 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -63,6 +63,7 @@ Gerir pastas incluídas Adicionar pasta Se possuir pastas com dados multimédia não reconhecidos pela aplicação, aqui pode adicioná-las manualmente. + Não foram encontrados ficheiros multimédia. Pode adicionar manualmente as pastas que contenham esses ficheiros. Redimensionar @@ -112,12 +113,14 @@ Incluir vídeos Incluir GIF Ordem aleatória - Utilizar animações Mover para trás Apresentação em ciclo + Animation + None + Fade + Slide Apresentação terminada Não foram encontrados ficheiros para a apresentação - Utilizar animação de transição Tipo de exibição @@ -130,10 +133,14 @@ Não agrupar ficheiros Pasta Última modificação + Last modified (daily) + Last modified (monthly) Data de obtenção + Date taken (daily) + Date taken (monthly) Tipo de ficheiro Extensão - Tenha em atenção de que o agrupamento e a ordenação são campos independentes + Tenha em atenção de que agrupamento e ordenação são campos independentes Pasta mostrada no widget: @@ -155,7 +162,7 @@ Fundo escuro e barra de estado no modo de ecrã completo Deslocação horizontal de miniaturas Ocultar interface do sistema se em ecrã completo - Apagar as pastas vazias depois de remover o seu conteúdo + Apagar pastas vazias depois de remover o seu conteúdo Permitir controlo do brilho das fotos com gestos verticais Permitir controlo do volume e do brilho dos vídeos através de gestos verticais Mostrar número de ficheiros na vista principal @@ -169,14 +176,14 @@ Mostrar reciclagem no ecrã de pastas Ampliação de imagens Mostrar fotos com a melhor qualidade possível - Mostrar a reciclagem como o último item do ecrã principal + Mostrar reciclagem como o último item do ecrã principal Sair de ecrã completo com um gesto para baixo Permitir ampliação 1:1 com dois toques Abrir vídeos em ecrã distinto com os novos toques horizontais Mostrar \"notch\", se disponível Permitir rotação de imagens com gestos Prioridade de carregamento dos ficheiros - velocidade + Velocidade Compromisso Não mostrar ficheiros inválidos @@ -225,16 +232,16 @@ - Simple Gallery Pro: Photo Manager & Editor + Simple Gallery Pro: Editor e gestor de fotos - Offline gallery without ads. Organize, edit, recover and protect photos & videos + Sem anúncios. Organize, edite, recupere e protega os seus vídeos e fotos - Simple Gallery Pro is a highly customizable offline gallery. Organize & edit your photos, recover deleted files with the recycle bin, protect & hide files and view a huge variety of different photo & video formats including RAW, SVG and much more. + Simple Gallery Pro é uma aplicação local para gerir fotos e vídeos. Pode organizar e editar as suas fotos, recuperar ficheiros através da reciclagem, proteger e ocultar ficheiros e ver imagens e vídeos disponíveis em vários formatos tais como RAW, SVG e muito mais. - The app contains no ads and unnecessary permissions. As the app doesn’t require internet access either, your privacy is protected. + A aplicação não tem anúncios nem pede permissões desnecessárias. uma vez que também não precisa de aceder à Internet, os seus ficheiros estão protegidos. ------------------------------------------------- - SIMPLE GALLERY PRO – FEATURES + SIMPLE GALLERY PRO – FUNCIONALIDADES ------------------------------------------------- • Offline gallery with no ads or popups diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 39de7f12a..06a4f65e0 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -63,6 +63,7 @@ Управление включёнными папками Добавить папку Если у вас есть папки, содержащие медиафайлы, но не распознанные приложением, вы можете добавить их вручную.\n\nДобавление папки не приводит к исключению каких-либо других. + Медиафайлы не найдены. Вы можете исправить данную проблему, добавив папки с медиафайлами вручную. Изменить размер @@ -112,12 +113,14 @@ Видео GIF В случайном порядке - Эффект затухания В обратном порядке Зациклить + Анимация + Нет + Затухание + Сдвиг Слайдшоу завершено Медиафайлов для слайдшоу не найдено - Эффект плавного перехода Вид @@ -130,7 +133,11 @@ Не группировать Папка Последнее изменение + Последнее изменение (по дням) + Последнее изменение (по месяцам) Дата съёмки + Дата съёмки (по дням) + Дата съёмки (по месяцам) Тип файла Расширение Обратите внимание, что группировка и сортировка — это два независимых поля @@ -225,7 +232,7 @@ - Simple Gallery Pro: Photo Manager & Editor + Галерея: управление и редактирование изображений Галерея без рекламы. Управление, изменение, восстановление и защита фото и видео diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 7c6cc27c5..f5e7965ad 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -63,6 +63,7 @@ Spravovať pridané priečinky Pridať priečinok Ak máte nejaké priečinky obsahujúce médiá, ale neboli rozpoznané aplikáciou, môžete ich tu manuálne pridať.\n\nPridanie nových položiek sem nevylúči žiadny iný priečinok. + Nenašli sa žiadne súbory s médiami. Viete to napraviť manuálnym pridaním priečinkov, ktoré obsahujú médiá. Zmeniť veľkosť @@ -112,12 +113,14 @@ Zahrnúť videá Zahrnúť GIFy Náhodné poradie - Používať miznúce animácie Ísť opačným smerom Automaticky reštartovať prezentáciu + Animácia: + Žiadna + Prelínanie + Posúvanie Prezentácia skončila Pre prezentáciu sa nenašli žiadne vhodné súbory - Použiť prelínacie animácie Zmeniť typ zobrazenia @@ -130,7 +133,11 @@ Nezoskupovať súbory Priečinka Dátumu poslednej úpravy + Dátumu poslednej úpravy (denne) + Dátumu poslednej úpravy (mesačne) Dátumu vytvorenia + Dátumu vytvorenia (denne) + Dátumu vytvorenia (mesačne) Typu súboru Prípony Prosím vedzte, že radenie a zoskupovanie súborov sú 2 nezávislé hodnoty diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 33db588cc..64d29cfe6 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -63,6 +63,7 @@ Urejaj vključene mape Dodaj mapo Če imate mape, ki vsebujejo medijske datoteke, ki jih aplikacija ni prepoznala, jih lahko ročno dodate tukaj.\n\nDodajanje novih elementov ne bo izključilo drugih. + No media files have been found. You can solve it by adding the folders containing media files manually. Spremeni velikost @@ -112,12 +113,14 @@ Vključi videoposnetke Vključi GIFe Naključni vrstni red - Uporabi zameglitev animacij Premik nazaj Ponavljaj diaprojekcijo + Animation + None + Fade + Slide Diaprojekcija se je zaključila Ne najdem datotek za diaprojekcijo - Uporabi križanje animacij Spremeni tip pogleda @@ -130,7 +133,11 @@ Ne združuj datotek Mapa Zadnjič spremenjeno + Last modified (daily) + Last modified (monthly) Posneto + Date taken (daily) + Date taken (monthly) Tip datoteke Končnica Združevanje in sortiranje sta dve neodvisni polji. diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 254e28851..deaca7956 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -63,6 +63,7 @@ Управљај укљученим фасциклама Додај фасциклу Ако имате неке фасцикле које садрже медију, али нису препознате од стране апликације, можете их додати ручно овде. \n\nДодавањем неких ставки овде нећете изузети неку другу фасциклу. + No media files have been found. You can solve it by adding the folders containing media files manually. Промена величине @@ -112,12 +113,14 @@ Садржи видео снимке Садржи ГИФове Насумични редослед - Користи изблеђујуће анимације Помери уназад Понављај слајдшоу + Animation + None + Fade + Slide Слајдшоу се завршио Нису пронађени медији за слајдшоу - Користи анимације са унакрсним изблеђивањем Промени тип прегледа @@ -130,7 +133,11 @@ Не групиши датотеке Фасцикла Задње измењено + Last modified (daily) + Last modified (monthly) Датум настанка + Date taken (daily) + Date taken (monthly) Тип датотеке Тип датотеке Имајте на уму да су груписање и сортирање 2 различите ствари diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 23ab204f7..6609790bb 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -63,6 +63,7 @@ Hantera inkluderade mappar Lägg till mapp Om du har vissa mappar som innehåller media men som inte känns igen av appen, kan du lägga till dem manuellt här. + No media files have been found. You can solve it by adding the folders containing media files manually. Ändra storlek @@ -112,12 +113,14 @@ Inkludera videor Inkludera GIF-bilder Spela upp i slumpmässig ordning - Använd toningsanimationer Spela upp i omvänd ordning Spela upp i en slinga + Animation + None + Fade + Slide Bildspelet har avslutats Ingen media hittades för bildspelet - Använd övertoningsanimationer Ändra vy @@ -130,7 +133,11 @@ Gruppera inte filer Mapp Senast ändrad + Last modified (daily) + Last modified (monthly) Fotodatum + Date taken (daily) + Date taken (monthly) Filtyp Filnamnstillägg Please note that grouping and sorting are 2 independent fields diff --git a/app/src/main/res/values-sw600dp/dimens.xml b/app/src/main/res/values-sw600dp/dimens.xml index 9703f1cb6..7ef1ff093 100644 --- a/app/src/main/res/values-sw600dp/dimens.xml +++ b/app/src/main/res/values-sw600dp/dimens.xml @@ -5,4 +5,5 @@ 30dp 38dp 70dp + 100dp diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index f5cf36ae0..a08a6b948 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -63,6 +63,7 @@ Dahil edilen klasörleri yönet Klasör ekle Medya içeren, ancak uygulama tarafından tanınmayan bazı klasörleriniz varsa, bunları elle ekleyebilirsiniz.\n\nBuraya bazı öğeler eklemek başka bir klasörü hariç tutmaz. + No media files have been found. You can solve it by adding the folders containing media files manually. Yeniden boyutlandır @@ -112,12 +113,14 @@ Videoları dahil et GIF\'leri dahil et Rastgele sırala - Soldurma animasyonlarını kullan Geriye doğru git Slayt gösterisini tekrarla + Animation + None + Fade + Slide Slayt gösterisi sona erdi Slayt gösterisi için medya bulunamadı - Çapraz geçiş animasyonlarını kullan Görünüm türünü değiştir @@ -130,7 +133,11 @@ Dosyaları gruplandırma Klasör Son değiştirilme + Last modified (daily) + Last modified (monthly) Çekildiği tarih + Date taken (daily) + Date taken (monthly) Dosya türü Uzantı Please note that grouping and sorting are 2 independent fields @@ -220,59 +227,59 @@ Görüntüleri görüntülemek için geçerli çözüm, vakaların büyük çoğunluğunda iyi çalışır, ama daha iyi görüntü kalitesi istiyorsanız, \"Derin yakınlaştırılabilir resimler\" bölümündeki uygulama ayarlarında \"Resimleri mümkün olan en yüksek kalitede göster\" seçeneğini etkinleştirebilirsiniz. Bir dosya/klasör gizledim. Nasıl gösterebilirim? Ana ekranda \"Geçici olarak gizli öğeleri göster\" menü öğesine veya gizli öğeyi görmek için uygulama ayarlarında \"Gizli öğeleri göster\" seçeneğine tıklayabilirsiniz. Göstermek isterseniz, sadece uzun basın ve \"Göster\"i seçin. Klasörler gizlenmiş bir \".nomedia\" dosyası ekleyerek gizlenir, dosyayı herhangi bir dosya yöneticisi ile de silebilirsiniz. - Why does the app take up so much space? - App cache can take up to 250MB, it ensures quicker image loading. If the app is taking up even more space, it is most likely caused by you having items in the Recycle Bin. Those files count to the app size. You can clear the Recycle bin by opening it and deleting all files, or from the app settings. Every file in the Bin is deleted automatically after 30 days. + Uygulama neden bu kadar yer kaplıyor? + Uygulama önbelleği 250 MB\'a kadar çıkabilir, daha hızlı resim yüklemesini sağlar. Uygulama daha da fazla yer kaplıyorsa, büyük olasılıkla Geri Dönüşüm Kutusu\'nda öğe bulundurmanızdan kaynaklanmaktadır. Bu dosyalar uygulama boyutuna göre sayılır. Geri Dönüşüm Kutusu\'nu açarak ve tüm dosyaları silerek ya da uygulama ayarlarından temizleyebilirsiniz. Geri dönüşümdeki her dosya 30 gün sonra otomatik olarak silinir. - Simple Gallery Pro: Photo Manager & Editor + Basit Galeri Pro: Fotoğraf Yönetici & Düzenleyici - Offline gallery without ads. Organize, edit, recover and protect photos & videos + Reklamsız çevrimdışı galeri. Fotoğraf & videolarınızı yönetin ve düzenleyin - Simple Gallery Pro is a highly customizable offline gallery. Organize & edit your photos, recover deleted files with the recycle bin, protect & hide files and view a huge variety of different photo & video formats including RAW, SVG and much more. + Basit Galeri Pro, özelleştirilebilir bir çevrimdışı galeridir. Fotoğraflarınızı düzenleyin ve organize edin, geri dönüşüm kutusuyla silinen dosyaları kurtarın, dosyaları koruyun ve gizleyin ve RAW, SVG ve çok daha fazlası dahil olmak üzere çok çeşitli fotoğraf ve video formatlarını görüntüleyin. - The app contains no ads and unnecessary permissions. As the app doesn’t require internet access either, your privacy is protected. + Uygulamaya hiçbir reklam ve gereksiz izinler içermez. Uygulama internet erişimi gerektirmediğinden gizliliğiniz de korunur. ------------------------------------------------- - SIMPLE GALLERY PRO – FEATURES + BASİT GALERİ PRO – ÖZELLİKLER ------------------------------------------------- - • Offline gallery with no ads or popups - • Simple gallery photo editor – crop, rotate, resize, draw, filters & more - • No internet access needed, giving you more privacy and security - • No unnecessary permissions required - • Quickly search images, videos & files - • Open & view many different photo and video types (RAW, SVG, panoramic etc) - • A variety of intuitive gestures to easily edit & organize files - • Lots of ways to filter, group & sort files - • Customize the appearance of Simple Gallery Pro - • Available in 32 languages - • Mark files as favorites for quick access - • Protect your photos & videos with a pattern, pin or fingerprint - • Use pin, pattern & fingerprint to protect the app launch or specific functions too - • Recover deleted photos & videos from the recycle bin - • Toggle visibility of files to hide photos & videos - • Create a customizable slideshow of your files - • View detailed information of your files (resolution, EXIF values etc) - • Simple Gallery Pro is open source - … and much much more! + • Reklamsız veya açılır penceresiz, çevrimdışı galeri + • Basit galeri fotoğraf editörü - kırpma, döndürme, yeniden boyutlandırma, çizim, filtreler ve daha fazlası + • İnternet erişimi gerekmez, size daha fazla gizlilik ve güvenlik sunar + • Gereksiz izinler gerekmez + • Resimleri, videoları ve dosyaları hızlıca arama + • Birçok farklı fotoğraf ve video türünü (RAW, SVG, panoramik vb.) açma ve görüntüleme + • Dosyaları kolayca düzenlemek ve organize etmek için çeşitli sezgisel hareketler + • Dosyaları filtrelemenin, gruplandırmanın ve sıralamanın birçok yolu + • Basit Galeri Pro\'nun görünümünü özelleştirme + • 32 dilde mevcut + • Hızlı erişim için dosyaları sık kullanılan olarak işaretleme + • Fotoğraflarınızı ve videolarınızı desen, pin veya parmak izi ile koruma + • Uygulama başlatılmasını veya belirli işlevleri de korumak için pin, desen ve parmak izi kullanma + • Silinen fotoğrafları ve videoları geri dönüşüm kutusundan kurtarma + • Fotoğrafları ve videoları gizlemek için dosyaların görünürlüğünü değiştirme + • Dosyalarınızın özelleştirilebilir bir slayt gösterisini oluşturma + • Dosyalarınızın ayrıntılı bilgilerini (çözünürlük, EXIF değerleri vb.) görüntüleme + • Basit Galeri Pro açık kaynak kodludur + … ve çok daha fazlası! - PHOTO GALLERY EDITOR - Simple Gallery Pro makes it easy to edit your pictures on the fly. Crop, flip, rotate and resize your pictures. If you’re feeling a little more creative you can add filters and draw on your pictures! + FOTOĞRAF GALERİSİ EDİTÖRÜ + Basit Galeri Pro, fotoğraflarınızı anında düzenlemenizi kolaylaştırır. Resimlerinizi kırpın, çevirin, döndürün ve yeniden boyutlandırın. Kendinizi biraz daha yaratıcı hissediyorsanız, filtre ekleyebilir ve resimlerinizi çizebilirsiniz! - SUPPORT FOR MANY FILE TYPES - Unlike some other gallery viewers & photo organizers, Simple Gallery Pro supports a huge range of different file types including JPEG, PNG, MP4, MKV, RAW, SVG, Panoramic photos, Panoramic videos and many more. + BİRÇOK DOSYA TÜRÜ İÇİN DESTEK + Diğer galeri görüntüleyicilerinden ve fotoğraf düzenleyicilerinden farklı olarak, Basit Galeri Pro, JPEG, PNG, MP4, MKV, RAW, SVG, Panoramik fotoğraflar, Panoramik videolar ve daha pek çok farklı dosya türünü destekler. - HIGHLY CUSTOMIZABLE GALLERY MANAGER - From the UI to the function buttons on the bottom toolbar, Simple Gallery Pro is highly customizable and works the way you want it to. No other gallery manager has this kind of flexibility! Thanks to being open source, we’re also available in 32 languages! + SON DERECE ÖZELLEŞTİRİLEBİLİR GALERİ YÖNETİCİSİ + Kullanıcı arayüzünden alt araç çubuğundaki işlev düğmelerine kadar, Basit Galeri Pro oldukça özelleştirilebilirdir ve istediğiniz şekilde çalışır. Başka hiçbir galeri yöneticisi bu tür bir esnekliğe sahip değildir! Açık kaynak olması sayesinde 32 dilde de kullanıma hazırız! - RECOVER DELETED PHOTOS & VIDEOS - Accidentally deleted a precious photo or video? Don’t worry! Simple Gallery Pro features a handy recycle bin where you can recover deleted photos & videos easily. + SİLİNEN FOTOĞRAFLARI VE VİDEOLARI KURTARIN + Yanlışlıkla önemli bir fotoğrafı veya videoyu mu sildiniz? Endişelenmeyin! Basit Galeri Pro, silinmiş fotoğrafları ve videoları kolayca kurtarabileceğiniz kullanışlı bir geri dönüşüm kutusuna sahiptir. - PROTECT & HIDE PHOTOS, VIDEOS & FILES - Using pin, pattern or your device’s fingerprint scanner you can protect and hide photos, videos & entire albums. You can protect the app itself or place locks on specific functions of the app. For example, you can’t delete a file without a fingerprint scan, helping to protect your files from accidental deletion. + FOTOĞRAFLARI, VİDEOLARI VE DOSYALARI KORUYUN VE GİZLEYİN + Pin, desen veya cihazınızın parmak izi tarayıcısını kullanarak fotoğrafları, videoları ve albümün tamamını koruyabilir ve gizleyebilirsiniz. Uygulamanın kendisini koruyabilir veya uygulamanın belirli işlevlerine kilitler yerleştirebilirsiniz. Örneğin, parmak izi taraması olmadan bir dosyayı silemez ve dosyalarınızı yanlışlıkla silmeye karşı korumaya yardımcı olabilirsiniz. - Check out the full suite of Simple Tools here: + Tüm Basit Araçlar paketini buradan inceleyin: https://www.simplemobiletools.com Facebook: diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index a20a87400..45f3bfb7e 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -14,7 +14,7 @@ Перемкнути у перегляд за теками Інша тека Показати на мапі - Невідоме місцерозташування + Невідоме розташування Збільшити кількість колонок Зменшити кількість колонок Змінити обкладинку @@ -32,7 +32,7 @@ Виправлення… Дати успішно виправлені Поділитися зображенням іншого розміру - Йой,\n\nздається, ви перейшли зі старого безкоштовного додатку на цей. Тепер ви можете видалити стару версію, у якій є кнопка \"Перейти на Pro\" вгорі налаштувань додатку.\n\nВи втратите лише елементи з Кошика, позначки улюблених елементів, а також потрібно буде скинути ваші налаштування додатку.\n\nДякую! + Агов,\n\nздається, ви оновились зі старого безкоштовного додатка. Тепер ви можете видалити стару версію, у якій є кнопка \"Перейти на Pro\" вгорі налаштувань додатка.\n\nВи втратите лише елементи з Кошика, позначки улюблених елементів, а також потрібно буде скинути ваші налаштування додатка.\n\nДякую! Фільтр мультимедійних файлів @@ -63,6 +63,7 @@ Керування включеними теками Додати теку Якщо у вас є теки з медіафайлами, але вони не були розпізнані додатком, ви можете додати їх тут вручну.\n\nДодавання елементів сюди не виключить будь-яку іншу теку. + Жоден медіафайл не знайдено. Ви можете додати теки з медіафайлами вручну, щоб вирішити цю проблему. Змінити розмір @@ -99,8 +100,8 @@ Встановити шпалери за допомогою: Встановлення шпалер… Шпалери успішно встановлено - Співвідношення сторін в портретній орієнтації - Співвідношення сторін в ландшафтній орієнтації + Співвідношення сторін у портретній орієнтації + Співвідношення сторін у ландшафтній орієнтації Домашній екран Екран блокування Домашній екран і екран блокування @@ -112,12 +113,14 @@ Включити відео Включити GIF-зображення Випадковий порядок - Використовувати анімацію затухання Рухатися назад Зациклити показ слайдів + Animation + None + Fade + Slide Слайдшоу закінчено Не знайдено медіафайлів для показу у слайдшоу - Анімувати перехід між елементами Змінити тип перегляду @@ -130,7 +133,11 @@ Не групувати файли текою останньою зміною + Last modified (daily) + Last modified (monthly) датою зйомки + Date taken (daily) + Date taken (monthly) типом файлу розширенням Зверніть увагу, що групування і сортування - це два окремих поля @@ -145,7 +152,7 @@ Перемкнути відображення імені файлу Зациклити відео Анімувати ескізи GIF-файлів - Максимальна яскравість екрану при повноекранному перегляді медіафайлу + Максимальна яскравість екрана при повноекранному перегляді медіафайлу Обрізати ескізи у квадрат Показувати тривалість відео При повноекранному перегляді обертати за… @@ -162,10 +169,10 @@ Показувати розширені подробиці при повноекранному перегляді Керування розширеними подробицями Дозволити масштабування одним пальцем при повноекранному перегляді - Дозволити миттєво змінювати медіафайл натисканням на сторони екрану + Дозволити миттєво змінювати медіафайл натисканням на сторони екрана Дозволити глибоке масштабування зображень Приховати розширені подробиці, коли рядок стану прихований - Показати деякі кнопки дій внизу екрану + Показати деякі кнопки дій внизу екрана Показувати \"Кошик\" на головному екрані Глибокомасштабовані зображення Показувати зображення в найвищій можливій якості @@ -184,10 +191,10 @@ Ескізи Повноекранний перегляд Розширені подробиці - Кнопки дій внизу екрану + Кнопки дій внизу екрана - Керування видимими кнопками дій внизу екрану + Керування видимими кнопками дій внизу екрана Перемкнути улюблене Перемкнути видимість файлу @@ -195,7 +202,7 @@ Як зробити Simple Gallery галереєю за-замовчуванням? Спочатку необхідно знайти поточну галерею за-замовчуванням в розділі \"Додатки\" налаштувань вашого пристрою. Знайдіть і натисніть на кнопку \"Використовувати за-замовчуванням\" абощо, потім оберіть \"Очистити замовчування\". Наступного разу коли ви намагатиметеся відкрити зображення або відео, ви побачите вікно з вибором додатків для цього. Оберіть Simple Gallery та зробіть його додатком за-замовчуванням. - Я заблокував додаток за допомогою паролю і забув його. Що я можу зробити? + Я заблокував додаток за допомогою пароля і забув його. Що я можу зробити? Ви можете вирішити цю проблему двома способами: перевстановити додаток або знайти його в розділі \"Додатки\" налаштувань вашого пристрою та обрати \"Очистити дані\". Це скине усі ваші налаштування додатка, але не видалить жодного медіафайлу. Як зробити альбом завжди доступним у верхній частині? Ви можете виконати довге натискання на бажаному альбомі і вибрати піктограму \"Закріпити\" у меню дій, що закріпить його вгорі. Ви також можете закріпити декілька тек; закріплені елементи будуть відсортовані за методом сортування за-замовчуванням. @@ -217,11 +224,11 @@ Сортування за датою зйомки, здається, працює некоректно. Як я можу це виправити? Найбільш вірогідна причина цього - копіювання фалів з іншого місця. Це можна виправити, обравши ескізи файлів і потім - \"Виправити дату зйомки\". Я бачу деякі кольорові нашарування на зображенні. Як я можу покращити якість? - Поточне рішення для показу зображень відмінно працює в переважній більшості випадків, але якщо вам потрібна ще краща якість зображень, ви можете увімкнути опцію \"Показувати зображення в найвищій можливій якості\" в розділі \"Глибокомасштабовані зображення\" налаштувань додатку. + Поточне рішення для показу зображень відмінно працює в переважній більшості випадків, але якщо вам потрібна ще краща якість зображень, ви можете увімкнути опцію \"Показувати зображення в найвищій можливій якості\" в розділі \"Глибокомасштабовані зображення\" налаштувань додатка. Я приховав файл / теку. Як я можу відмінити цю дію? - Щоб побачити приховані елементи, ви можете або натиснути пункт меню \"Тимчасово показати приховані елементи\" на головному екрані, або перемкнути опцію \"Показати приховані елементи\" в налаштуваннях додатку. Якщо ви більше не хочете приховувати елемент, довго натисніть на нього і оберіть \"Не приховувати\". Теки приховуються шляхом створення прихованого файлу \".nomedia\" в них, тож ви також можете видалити цей файл будь-яким файловим менеджером. + Щоб побачити приховані елементи, ви можете або натиснути пункт меню \"Тимчасово показати приховані елементи\" на головному екрані, або перемкнути опцію \"Показати приховані елементи\" в налаштуваннях додатка. Якщо ви більше не хочете приховувати елемент, довго натисніть на нього і оберіть \"Не приховувати\". Теки приховуються шляхом створення прихованого файлу \".nomedia\" в них, тож ви також можете видалити цей файл будь-яким файловим менеджером. Чому додаток займає так багато місця? - Кеш додатку може займати до 500 МБ, він забезпечує швидше завантаження зображень. Якщо додаток займає ще більше місця, найбільш вірогідно, це спричинено видаленими елементами у Кошику. Вони враховуються у загальному розмірі додатку. Ви можете очистити Кошик, відкривши його та видаливши всі файли, або через налаштування додатку. Кожен файл у Кошику автоматично видаляється через 30 днів. + Кеш додатка може займати до 500 МБ, він забезпечує швидше завантаження зображень. Якщо додаток займає ще більше місця, найбільш вірогідно, це спричинено видаленими елементами у Кошику. Вони враховуються у загальному розмірі додатка. Ви можете очистити Кошик, відкривши його та видаливши всі файли, або через налаштування додатка. Кожен файл у Кошику автоматично видаляється через 30 днів. @@ -270,7 +277,7 @@ Випадково видалили дорогоцінне фото чи відео? Не хвилюйтеся! Simple Gallery Pro пропонує зручний кошик, звідки можна легко відновити видалені фото і відео. ЗАХИЩАЙТЕ І ПРИХОВУЙТЕ ФОТО, ВІДЕО І ФАЙЛИ - Використовуючи PIN-код, графічний ключ чи сканер відбитку пальця на вашому пристрої, ви можете захистити та приховати фото, відео та цілі альбоми. Ви можете захистити сам додаток або заблокувати окремі його функції. Наприклад, заборона видалення файлів без сканування відбитку пальця допоможе захистити ваші файли від випадкового видалення. + Використовуючи PIN-код, графічний ключ чи сканер відбитка пальця на вашому пристрої, ви можете захистити та приховати фото, відео та цілі альбоми. Ви можете захистити сам додаток або заблокувати окремі його функції. Наприклад, заборона видалення файлів без сканування відбитку пальця допоможе захистити ваші файли від випадкового видалення. Перегляньте повний набір додатків Simple Tools тут: https://www.simplemobiletools.com diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 73947644d..bfff3f9f3 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -63,6 +63,7 @@ 管理包含目录 添加目录 如果您还有应用未扫描到的媒体文件,请添加所在目录路径。 + 没有找到媒体文件。请手动添加包含媒体文件的文件夹。 缩放 @@ -112,12 +113,14 @@ 包括视频 包括 GIFs 随机顺序 - 使用渐变动画 倒播 循环幻灯片 + Animation + None + Fade + Slide 幻灯片结束 未发现可用媒体 - 使用淡入淡出动画 更改视图类型 @@ -130,7 +133,11 @@ 禁用文件分组 目录 最近修改 + Last modified (daily) + Last modified (monthly) 拍摄时间 + Date taken (daily) + Date taken (monthly) 文件类型 扩展名 请注意,分组和排序是相互独立的 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index dce671369..5dd4781fe 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -63,6 +63,7 @@ 管理包含資料夾 增加資料夾 如果有些資料夾含有媒體檔案,卻沒被辨識到,您可以在此手動加入。 + No media files have been found. You can solve it by adding the folders containing media files manually. 縮放 @@ -112,12 +113,14 @@ 包含影片 包含GIF 隨機順序 - 使用淡入淡出動畫 反向播放 投影片循環 + Animation + None + Fade + Slide 投影片結束 找不到投影片的媒體檔案 - 使用淡入淡出動畫 改變瀏覽類型 @@ -130,7 +133,11 @@ 不歸類檔案 資料夾 最後修改 + Last modified (daily) + Last modified (monthly) 拍照日期 + Date taken (daily) + Date taken (monthly) 檔案類型 副檔名 請注意,歸類和排序是兩者是獨立的 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index dce671369..0c557e7a4 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -28,7 +28,7 @@ 強制直向 強制橫向 使用預設方向 - 修復拍照日期數值 + 修復拍攝日期數值 修復中… 日期修復成功 分享調整大小的版本 @@ -63,6 +63,7 @@ 管理包含資料夾 增加資料夾 如果有些資料夾含有媒體檔案,卻沒被辨識到,您可以在此手動加入。 + 未發現媒體檔案。您可以手動添加包含媒體檔案的資料夾來解決。 縮放 @@ -112,12 +113,14 @@ 包含影片 包含GIF 隨機順序 - 使用淡入淡出動畫 反向播放 投影片循環 + 動畫 + + 漸變 + 滑動 投影片結束 找不到投影片的媒體檔案 - 使用淡入淡出動畫 改變瀏覽類型 @@ -130,7 +133,11 @@ 不歸類檔案 資料夾 最後修改 - 拍照日期 + 最後修改 (按日) + 最後修改 (按月) + 拍攝日期 + 拍攝日期 (按日) + 拍攝日期 (按月) 檔案類型 副檔名 請注意,歸類和排序是兩者是獨立的 @@ -213,9 +220,9 @@ 我可以用這程式裁減圖片嗎? 是的,你能夠在編輯器內拉動圖片角落來裁剪圖片。要進入編輯器,你可以長按圖片縮圖然後選擇[編輯],或是在全螢幕檢視下選擇[編輯]。 我可以歸類媒體檔案的縮圖嗎? - 當然,只要在縮圖瀏覽中使用[歸類]選單項目就可以了。你能依多種條件歸類檔案,包含拍照日期。如果你使用了[資料夾內容全部顯示]功能,你還能以資料夾來歸類。 - 依拍照日期排序似乎沒正確運作,我該如何修復? - 那很可能是由於檔案從某處複製過來所造成的。你可以選擇檔案縮圖,然後選擇\"修復拍照日期數值\"來進行修復。 + 當然,只要在縮圖瀏覽中使用[歸類]選單項目就可以了。你能依多種條件歸類檔案,包含拍攝日期。如果你使用了[資料夾內容全部顯示]功能,你還能以資料夾來歸類。 + 依拍攝日期排序似乎沒正確運作,我該如何修復? + 那很可能是由於檔案從某處複製過來所造成的。你可以選擇檔案縮圖,然後選擇\"修復拍攝日期數值\"來進行修復。 我在圖片上看到一些色彩條紋。我如何提升品質? 目前顯示圖片的處理方法,在大部分情況下都能正常運行。但如果你想要更好的圖片品質,你可以在程式設定中[可深度縮放的圖片]部分,啟用[以最高品質顯示圖片]。 我隱藏了一個檔案/資料夾。我如何取消隱藏? diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml index 1ba77d374..cc7e8155c 100644 --- a/app/src/main/res/values/integers.xml +++ b/app/src/main/res/values/integers.xml @@ -4,5 +4,5 @@ 3 4 - 1026 + 33794 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a91c739e5..6b7b65968 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -63,6 +63,7 @@ Manage included folders Add folder If you have some folders which contain media, but were not recognized by the app, you can add them manually here.\n\nAdding some items here will not exclude any other folder. + No media files have been found. You can solve it by adding the folders containing media files manually. Resize @@ -112,12 +113,14 @@ Include videos Include GIFs Random order - Use fade animations Move backwards Loop slideshow + Animation + None + Fade + Slide The slideshow ended No media for the slideshow have been found - Use crossfade animations Change view type @@ -130,7 +133,11 @@ Do not group files Folder Last modified + Last modified (daily) + Last modified (monthly) Date taken + Date taken (daily) + Date taken (monthly) File type Extension Please note that grouping and sorting are 2 independent fields diff --git a/build.gradle b/build.gradle index fbf166032..bfe902f73 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.31' + ext.kotlin_version = '1.3.40' repositories { google() @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.4.0' + classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong