diff --git a/CHANGELOG.md b/CHANGELOG.md index 4679c2ccb..ca94b74d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ Changelog ========== +Version 6.2.2 *(2019-01-10)* +---------------------------- + + * Reverted to the old way of playing videos, opening them on a separate screen can be enabled in the app settings + * Added some memory related improvements at displaying fullscreen images + * Allow showing videos in slideshows + Version 6.2.1 *(2019-01-08)* ---------------------------- diff --git a/app/build.gradle b/app/build.gradle index e0cd7c297..8e1c23607 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { applicationId "com.simplemobiletools.gallery.pro" minSdkVersion 21 targetSdkVersion 28 - versionCode 219 - versionName "6.2.1" + versionCode 220 + versionName "6.2.2" multiDexEnabled true setProperty("archivesBaseName", "gallery") } @@ -57,7 +57,7 @@ android { } dependencies { - implementation 'com.simplemobiletools:commons:5.6.6' + implementation 'com.simplemobiletools:commons:5.6.7' 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' @@ -78,7 +78,7 @@ dependencies { //implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0' //implementation 'com.github.tibbi:subsampling-scale-image-view:v3.10.1-fork' - implementation 'com.github.tibbi:subsampling-scale-image-view:7a000e651e' + implementation 'com.github.tibbi:subsampling-scale-image-view:9e9a393cc3' // implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation 'com.github.tibbi:PhotoView:2.3.0-fork' diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/EditActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/EditActivity.kt index f665296be..be4ce6d94 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/EditActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/EditActivity.kt @@ -18,17 +18,20 @@ import android.widget.RelativeLayout import androidx.recyclerview.widget.LinearLayoutManager import com.bumptech.glide.Glide import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.DecodeFormat 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.ColorPickerDialog import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.OTG_PATH import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE import com.simplemobiletools.commons.helpers.REAL_FILE_PATH import com.simplemobiletools.commons.helpers.isNougatPlus import com.simplemobiletools.commons.models.FileDirItem +import com.simplemobiletools.gallery.pro.BuildConfig import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.adapters.FiltersAdapter import com.simplemobiletools.gallery.pro.dialogs.OtherAspectRatioDialog @@ -45,6 +48,7 @@ import kotlinx.android.synthetic.main.activity_edit.* import kotlinx.android.synthetic.main.bottom_actions_aspect_ratio.* import kotlinx.android.synthetic.main.bottom_editor_actions_filter.* import kotlinx.android.synthetic.main.bottom_editor_crop_rotate_actions.* +import kotlinx.android.synthetic.main.bottom_editor_draw_actions.* import kotlinx.android.synthetic.main.bottom_editor_primary_actions.* import java.io.* @@ -55,6 +59,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener } } + private val TEMP_FOLDER_NAME = "images" private val ASPECT_X = "aspectX" private val ASPECT_Y = "aspectY" private val CROP = "crop" @@ -63,6 +68,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener private val PRIMARY_ACTION_NONE = 0 private val PRIMARY_ACTION_FILTER = 1 private val PRIMARY_ACTION_CROP_ROTATE = 2 + private val PRIMARY_ACTION_DRAW = 3 private val CROP_ROTATE_NONE = 0 private val CROP_ROTATE_ASPECT_RATIO = 1 @@ -71,15 +77,17 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener private lateinit var saveUri: Uri private var resizeWidth = 0 private var resizeHeight = 0 + private var drawColor = 0 private var lastOtherAspectRatio: Pair? = null private var currPrimaryAction = PRIMARY_ACTION_NONE private var currCropRotateAction = CROP_ROTATE_NONE private var currAspectRatio = ASPECT_RATIO_FREE private var isCropIntent = false private var isEditingWithThirdParty = false + private var isSharingBitmap = false + private var wasDrawCanvasPositioned = false private var oldExif: ExifInterface? = null - - private var initialBitmap: Bitmap? = null + private var filterInitialBitmap: Bitmap? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -95,6 +103,33 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener } } + override fun onResume() { + super.onResume() + isEditingWithThirdParty = false + } + + override fun onStop() { + super.onStop() + if (isEditingWithThirdParty) { + finish() + } + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.menu_editor, menu) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.save_as -> saveImage() + R.id.edit -> editWith() + R.id.share -> shareImage() + else -> return super.onOptionsItemSelected(item) + } + return true + } + private fun initEditActivity() { if (intent.data == null) { toast(R.string.invalid_image_path) @@ -150,35 +185,10 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener updateAspectRatio(config.lastEditorCropAspectRatio) } - override fun onResume() { - super.onResume() - isEditingWithThirdParty = false - } - - override fun onStop() { - super.onStop() - if (isEditingWithThirdParty) { - finish() - } - } - - override fun onCreateOptionsMenu(menu: Menu): Boolean { - menuInflater.inflate(R.menu.menu_editor, menu) - return true - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { - R.id.save_as -> saveImage() - R.id.edit -> editWith() - else -> return super.onOptionsItemSelected(item) - } - return true - } - private fun loadDefaultImageView() { default_image_view.beVisible() crop_image_view.beGone() + editor_draw_canvas.beGone() val options = RequestOptions() .skipMemoryCache(true) @@ -193,21 +203,22 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener override fun onResourceReady(bitmap: Bitmap?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { val currentFilter = getFiltersAdapter()?.getCurrentFilter() - if (initialBitmap == null) { + if (filterInitialBitmap == null) { loadCropImageView() bottomCropRotateClicked() } - if (initialBitmap != null && currentFilter != null && currentFilter.filter.name != getString(R.string.none)) { + if (filterInitialBitmap != null && currentFilter != null && currentFilter.filter.name != getString(R.string.none)) { default_image_view.onGlobalLayout { applyFilter(currentFilter) } } else { - initialBitmap = bitmap + filterInitialBitmap = bitmap } if (isCropIntent) { bottom_primary_filter.beGone() + bottom_primary_draw.beGone() } return false @@ -217,6 +228,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener private fun loadCropImageView() { default_image_view.beGone() + editor_draw_canvas.beGone() crop_image_view.apply { beVisible() setOnCropImageCompleteListener(this@EditActivity) @@ -231,6 +243,52 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener } } + private fun loadDrawCanvas() { + default_image_view.beGone() + crop_image_view.beGone() + editor_draw_canvas.beVisible() + + if (!wasDrawCanvasPositioned) { + wasDrawCanvasPositioned = true + editor_draw_canvas.onGlobalLayout { + Thread { + fillCanvasBackground() + }.start() + } + } + } + + private fun fillCanvasBackground() { + val size = Point() + windowManager.defaultDisplay.getSize(size) + val options = RequestOptions() + .format(DecodeFormat.PREFER_ARGB_8888) + .skipMemoryCache(true) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .fitCenter() + + try { + val builder = Glide.with(applicationContext) + .asBitmap() + .load(uri) + .apply(options) + .into(editor_draw_canvas.width, editor_draw_canvas.height) + + val bitmap = builder.get() + runOnUiThread { + editor_draw_canvas.apply { + updateBackgroundBitmap(bitmap) + layoutParams.width = bitmap.width + layoutParams.height = bitmap.height + y = (height - bitmap.height) / 2f + requestLayout() + } + } + } catch (e: Exception) { + showErrorToast(e) + } + } + @TargetApi(Build.VERSION_CODES.N) private fun saveImage() { var inputStream: InputStream? = null @@ -246,6 +304,18 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener if (crop_image_view.isVisible()) { crop_image_view.getCroppedImageAsync() + } else if (editor_draw_canvas.isVisible()) { + val bitmap = editor_draw_canvas.getBitmap() + if (saveUri.scheme == "file") { + SaveAsDialog(this, saveUri.path, true) { + saveBitmapToFile(bitmap, it, true) + } + } else if (saveUri.scheme == "content") { + val filePathGetter = getNewFilePath() + SaveAsDialog(this, filePathGetter.first, filePathGetter.second) { + saveBitmapToFile(bitmap, it, true) + } + } } else { val currentFilter = getFiltersAdapter()?.getCurrentFilter() ?: return val filePathGetter = getNewFilePath() @@ -271,12 +341,77 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener } } + private fun shareImage() { + Thread { + when { + default_image_view.isVisible() -> { + val currentFilter = getFiltersAdapter()?.getCurrentFilter() + if (currentFilter == null) { + toast(R.string.unknown_error_occurred) + } + + val originalBitmap = Glide.with(applicationContext).asBitmap().load(uri).submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).get() + currentFilter!!.filter.processFilter(originalBitmap) + shareBitmap(originalBitmap) + } + crop_image_view.isVisible() -> { + isSharingBitmap = true + runOnUiThread { + crop_image_view.getCroppedImageAsync() + } + } + 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) + + val folder = File(cacheDir, TEMP_FOLDER_NAME) + if (!folder.exists()) { + if (!folder.mkdir()) { + callback(null) + return + } + } + + val filename = applicationContext.getFilenameFromContentUri(saveUri) ?: "tmp.jpg" + val newPath = "$folder/$filename" + val fileDirItem = FileDirItem(newPath, filename) + getFileOutputStream(fileDirItem, true) { + if (it != null) { + try { + it.write(bytes.toByteArray()) + callback(newPath) + } catch (e: Exception) { + } finally { + it.close() + } + } else { + callback("") + } + } + } + + private fun shareBitmap(bitmap: Bitmap) { + getTempImagePath(bitmap) { + if (it != null) { + sharePathIntent(it, BuildConfig.APPLICATION_ID) + } else { + toast(R.string.unknown_error_occurred) + } + } + } + private fun getFiltersAdapter() = bottom_actions_filter_list.adapter as? FiltersAdapter private fun setupBottomActions() { setupPrimaryActionButtons() setupCropRotateActionButtons() setupAspectRatioButtons() + setupDrawButtons() } private fun setupPrimaryActionButtons() { @@ -287,6 +422,10 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener bottom_primary_crop_rotate.setOnClickListener { bottomCropRotateClicked() } + + bottom_primary_draw.setOnClickListener { + bottomDrawClicked() + } } private fun bottomFilterClicked() { @@ -307,6 +446,15 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener updatePrimaryActionButtons() } + private fun bottomDrawClicked() { + currPrimaryAction = if (currPrimaryAction == PRIMARY_ACTION_DRAW) { + PRIMARY_ACTION_NONE + } else { + PRIMARY_ACTION_DRAW + } + updatePrimaryActionButtons() + } + private fun setupCropRotateActionButtons() { bottom_rotate.setOnClickListener { crop_image_view.rotateImage(90) @@ -368,26 +516,60 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener updateAspectRatioButtons() } + private fun setupDrawButtons() { + updateDrawColor(config.lastEditorDrawColor) + bottom_draw_width.progress = config.lastEditorBrushSize + updateBrushSize(config.lastEditorBrushSize) + + bottom_draw_color_clickable.setOnClickListener { + ColorPickerDialog(this, drawColor) { wasPositivePressed, color -> + if (wasPositivePressed) { + updateDrawColor(color) + } + } + } + + bottom_draw_width.onSeekBarChangeListener { + config.lastEditorBrushSize = it + updateBrushSize(it) + } + + bottom_draw_undo.setOnClickListener { + editor_draw_canvas.undo() + } + } + + private fun updateBrushSize(percent: Int) { + editor_draw_canvas.updateBrushSize(percent) + val scale = Math.max(0.03f, percent / 100f) + bottom_draw_color.scaleX = scale + bottom_draw_color.scaleY = scale + } + private fun updatePrimaryActionButtons() { if (crop_image_view.isGone() && currPrimaryAction == PRIMARY_ACTION_CROP_ROTATE) { loadCropImageView() } else if (default_image_view.isGone() && currPrimaryAction == PRIMARY_ACTION_FILTER) { loadDefaultImageView() + } else if (editor_draw_canvas.isGone() && currPrimaryAction == PRIMARY_ACTION_DRAW) { + loadDrawCanvas() } - arrayOf(bottom_primary_filter, bottom_primary_crop_rotate).forEach { + arrayOf(bottom_primary_filter, bottom_primary_crop_rotate, bottom_primary_draw).forEach { it.applyColorFilter(Color.WHITE) } val currentPrimaryActionButton = when (currPrimaryAction) { PRIMARY_ACTION_FILTER -> bottom_primary_filter PRIMARY_ACTION_CROP_ROTATE -> bottom_primary_crop_rotate + PRIMARY_ACTION_DRAW -> bottom_primary_draw else -> null } currentPrimaryActionButton?.applyColorFilter(config.primaryColor) bottom_editor_filter_actions.beVisibleIf(currPrimaryAction == PRIMARY_ACTION_FILTER) bottom_editor_crop_rotate_actions.beVisibleIf(currPrimaryAction == PRIMARY_ACTION_CROP_ROTATE) + bottom_editor_draw_actions.beVisibleIf(currPrimaryAction == PRIMARY_ACTION_DRAW) if (currPrimaryAction == PRIMARY_ACTION_FILTER && bottom_actions_filter_list.adapter == null) { Thread { @@ -436,7 +618,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener } private fun applyFilter(filterItem: FilterItem) { - val newBitmap = Bitmap.createBitmap(initialBitmap) + val newBitmap = Bitmap.createBitmap(filterInitialBitmap) default_image_view.setImageBitmap(filterItem.filter.processFilter(newBitmap)) } @@ -490,6 +672,13 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener primaryActionView?.applyColorFilter(config.primaryColor) } + private fun updateDrawColor(color: Int) { + drawColor = color + bottom_draw_color.applyColorFilter(color) + config.lastEditorDrawColor = color + editor_draw_canvas.updateColor(color) + } + private fun resizeImage() { val point = getAreaSize() if (point == null) { @@ -525,15 +714,22 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener override fun onCropImageComplete(view: CropImageView, result: CropImageView.CropResult) { if (result.error == null) { + val bitmap = result.bitmap + if (isSharingBitmap) { + isSharingBitmap = false + shareBitmap(bitmap) + return + } + if (isCropIntent) { if (saveUri.scheme == "file") { - saveBitmapToFile(result.bitmap, saveUri.path, true) + saveBitmapToFile(bitmap, saveUri.path, true) } else { var inputStream: InputStream? = null var outputStream: OutputStream? = null try { val stream = ByteArrayOutputStream() - result.bitmap.compress(CompressFormat.JPEG, 100, stream) + bitmap.compress(CompressFormat.JPEG, 100, stream) inputStream = ByteArrayInputStream(stream.toByteArray()) outputStream = contentResolver.openOutputStream(saveUri) inputStream.copyTo(outputStream) @@ -551,12 +747,12 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener } } else if (saveUri.scheme == "file") { SaveAsDialog(this, saveUri.path, true) { - saveBitmapToFile(result.bitmap, it, true) + saveBitmapToFile(bitmap, it, true) } } else if (saveUri.scheme == "content") { val filePathGetter = getNewFilePath() SaveAsDialog(this, filePathGetter.first, filePathGetter.second) { - saveBitmapToFile(result.bitmap, it, true) + saveBitmapToFile(bitmap, it, true) } } else { toast(R.string.unknown_file_location) @@ -633,7 +829,7 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener } private fun editWith() { - openEditor(uri.toString()) + openEditor(uri.toString(), true) isEditingWithThirdParty = true } 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 330e88e3d..6e4fa3240 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 @@ -927,7 +927,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { } mDirs = dirs.clone() as ArrayList - if (mDirs.size > 100) { + if (mDirs.size > 55) { excludeSpamFolders() } } @@ -1231,6 +1231,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener { add(Release(206, R.string.release_206)) add(Release(213, R.string.release_213)) add(Release(217, R.string.release_217)) + add(Release(220, R.string.release_220)) checkWhatsNew(this, BuildConfig.VERSION_CODE) } } 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 13572628f..5a474751e 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 @@ -558,7 +558,9 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { } mIsGettingMedia = true - if (!mLoadedInitialPhotos) { + if (mLoadedInitialPhotos) { + startAsyncTask() + } else { getCachedMedia(mPath, mIsGetVideoIntent, mIsGetImageIntent, mMediumDao) { if (it.isEmpty()) { runOnUiThread { @@ -569,9 +571,6 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener { } startAsyncTask() } - } else { - media_refresh_layout.isRefreshing = true - startAsyncTask() } mLoadedInitialPhotos = true 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 224b58325..02ddad7c1 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 @@ -72,7 +72,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList mUri = intent.data ?: return var filename = getFilenameFromUri(mUri!!) mIsFromGallery = intent.getBooleanExtra(IS_FROM_GALLERY, false) - if (mIsFromGallery && filename.isVideoFast()) { + if (mIsFromGallery && filename.isVideoFast() && config.openVideosOnSeparateScreen) { launchVideoPlayer() return } 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 eb292610f..df0324e07 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 @@ -42,6 +42,7 @@ class SettingsActivity : SimpleActivity() { setupAutoplayVideos() setupRememberLastVideo() setupLoopVideos() + setupOpenVideosOnSeparateScreen() setupAnimateGifs() setupMaxBrightness() setupCropThumbnails() @@ -174,6 +175,14 @@ class SettingsActivity : SimpleActivity() { } } + private fun setupOpenVideosOnSeparateScreen() { + settings_open_videos_on_separate_screen.isChecked = config.openVideosOnSeparateScreen + settings_open_videos_on_separate_screen_holder.setOnClickListener { + settings_open_videos_on_separate_screen.toggle() + config.openVideosOnSeparateScreen = settings_open_videos_on_separate_screen.isChecked + } + } + private fun setupAnimateGifs() { settings_animate_gifs.isChecked = config.animateGifs settings_animate_gifs_holder.setOnClickListener { 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 d47601c06..4c0f3614e 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 @@ -5,6 +5,7 @@ import android.content.Intent import android.content.pm.ActivityInfo import android.content.res.Configuration import android.graphics.Color +import android.graphics.Matrix import android.graphics.Point import android.graphics.SurfaceTexture import android.graphics.drawable.ColorDrawable @@ -43,19 +44,28 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen private var mScreenWidth = 0 private var mCurrTime = 0 private var mDuration = 0 - private var mVideoSize = Point(0, 0) + private var mSaveScale = 1f + private var mRight = 0f + private var mBottom = 0f + private var mLastTouchX = 0f + private var mLastTouchY = 0f private var mDragThreshold = 0f - - private var mUri: Uri? = null - private var mExoPlayer: SimpleExoPlayer? = null - private var mTimerHandler = Handler() - private var mPlayWhenReadyHandler = Handler() - private var mTouchDownX = 0f private var mTouchDownY = 0f private var mTouchDownTime = 0L private var mProgressAtDown = 0L private var mCloseDownThreshold = 100f + private var mCurrZoomMode = ZOOM_MODE_NONE + + private var mUri: Uri? = null + private var mExoPlayer: SimpleExoPlayer? = null + private var mVideoSize = Point(0, 0) + private var mTimerHandler = Handler() + private var mPlayWhenReadyHandler = Handler() + private var mScaleDetector: ScaleGestureDetector? = null + private var mMatrices = FloatArray(9) + private val mMatrix = Matrix() + private var mIgnoreCloseDown = false public override fun onCreate(savedInstanceState: Bundle?) { @@ -176,7 +186,7 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen } video_surface.setOnTouchListener { view, event -> - handleEvent(event) + handleEventWithZooming(event) true } @@ -185,11 +195,11 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen if (config.allowVideoGestures) { video_brightness_controller.initialize(this, slide_info, true, video_player_holder) { x, y -> - fullscreenToggled(!mIsFullscreen) + toggleFullscreen() } video_volume_controller.initialize(this, slide_info, false, video_player_holder) { x, y -> - fullscreenToggled(!mIsFullscreen) + toggleFullscreen() } } else { video_brightness_controller.beGone() @@ -199,10 +209,11 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen if (config.hideSystemUI) { Handler().postDelayed({ fullscreenToggled(true) - }, 500) + }, HIDE_SYSTEM_UI_DELAY) } mDragThreshold = DRAG_THRESHOLD * resources.displayMetrics.density + mScaleDetector = ScaleGestureDetector(applicationContext, ScaleListener()) } private fun initExoPlayer() { @@ -418,6 +429,10 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen } } + private fun toggleFullscreen() { + fullscreenToggled(!mIsFullscreen) + } + private fun fullscreenToggled(isFullScreen: Boolean) { mIsFullscreen = isFullScreen if (isFullScreen) { @@ -523,7 +538,8 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen val diffX = mTouchDownX - event.x val diffY = mTouchDownY - event.y - if (config.allowDownGesture && !mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold) { + val downGestureDuration = System.currentTimeMillis() - mTouchDownTime + if (config.allowDownGesture && !mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold && downGestureDuration < MAX_CLOSE_DOWN_GESTURE_DURATION) { supportFinishAfterTransition() } @@ -539,8 +555,8 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen togglePlayPause() } } else { - if (System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { - fullscreenToggled(!mIsFullscreen) + if (Math.abs(diffX) < CLICK_MAX_DISTANCE && Math.abs(diffY) < CLICK_MAX_DISTANCE && System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { + toggleFullscreen() } } mIsDragged = false @@ -615,6 +631,151 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen }.start() } - override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) { + override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {} + + private fun handleEventWithZooming(event: MotionEvent) { + mScaleDetector?.onTouchEvent(event) + + mMatrix.getValues(mMatrices) + val x = mMatrices[Matrix.MTRANS_X] + val y = mMatrices[Matrix.MTRANS_Y] + + when (event.actionMasked) { + MotionEvent.ACTION_DOWN -> { + mTouchDownTime = System.currentTimeMillis() + mCurrZoomMode = ZOOM_MODE_DRAG + mLastTouchX = event.x + mLastTouchY = event.y + + mTouchDownX = event.x + mTouchDownY = event.y + mProgressAtDown = mExoPlayer!!.currentPosition + } + MotionEvent.ACTION_UP -> { + mCurrZoomMode = ZOOM_MODE_NONE + val diffX = mTouchDownX - event.x + val diffY = mTouchDownY - event.y + + val downGestureDuration = System.currentTimeMillis() - mTouchDownTime + if (!mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold && downGestureDuration < MAX_CLOSE_DOWN_GESTURE_DURATION && mSaveScale == 1f) { + supportFinishAfterTransition() + } + mIgnoreCloseDown = false + + if (mIsDragged) { + if (mIsFullscreen) { + arrayOf(video_curr_time, video_seekbar, video_duration).forEach { + it.animate().alpha(0f).start() + } + } + + if (!mIsPlaying) { + togglePlayPause() + } + } else { + if (Math.abs(diffX) < CLICK_MAX_DISTANCE && Math.abs(diffY) < CLICK_MAX_DISTANCE && System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { + toggleFullscreen() + } + } + + mIsDragged = false + } + MotionEvent.ACTION_POINTER_DOWN -> { + mLastTouchX = event.x + mLastTouchY = event.y + mCurrZoomMode = ZOOM_MODE_ZOOM + mIgnoreCloseDown = true + } + MotionEvent.ACTION_MOVE -> { + val diffX = event.x - mTouchDownX + val diffY = event.y - mTouchDownY + if (mSaveScale == 1f && (mIsDragged || (Math.abs(diffX) > mDragThreshold && Math.abs(diffX) > Math.abs(diffY)))) { + if (!mIsDragged) { + arrayOf(video_curr_time, video_seekbar, video_duration).forEach { + it.animate().alpha(1f).start() + } + } + mIgnoreCloseDown = true + mIsDragged = true + var percent = ((diffX / mScreenWidth) * 100).toInt() + percent = Math.min(100, Math.max(-100, percent)) + + val skipLength = (mDuration * 1000f) * (percent / 100f) + var newProgress = mProgressAtDown + skipLength + newProgress = Math.max(Math.min(mExoPlayer!!.duration.toFloat(), newProgress), 0f) + val newSeconds = (newProgress / 1000).toInt() + setPosition(newSeconds) + resetPlayWhenReady() + } else if (mCurrZoomMode == ZOOM_MODE_ZOOM || mCurrZoomMode == ZOOM_MODE_DRAG && mSaveScale > MIN_VIDEO_ZOOM_SCALE) { + var deltaX = event.x - mLastTouchX + var deltaY = event.y - mLastTouchY + if (y + deltaY > 0) { + deltaY = -y + } else if (y + deltaY < -mBottom) { + deltaY = -(y + mBottom) + } + + if (x + deltaX > 0) { + deltaX = -x + } else if (x + deltaX < -mRight) { + deltaX = -(x + mRight) + } + + mMatrix.postTranslate(deltaX, deltaY) + mLastTouchX = event.x + mLastTouchY = event.y + } + } + MotionEvent.ACTION_POINTER_UP -> { + mCurrZoomMode = ZOOM_MODE_NONE + } + } + + video_surface.setTransform(mMatrix) + video_surface.invalidate() + } + + // taken from https://github.com/Manuiq/ZoomableTextureView + private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() { + override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { + mCurrZoomMode = ZOOM_MODE_ZOOM + return true + } + + override fun onScale(detector: ScaleGestureDetector): Boolean { + val width = video_surface.width + val height = video_surface.height + if (width <= 0 || height <= 0) { + return true + } + + var scaleFactor = detector.scaleFactor + val origScale = mSaveScale + mSaveScale *= scaleFactor + + if (mSaveScale > MAX_VIDEO_ZOOM_SCALE) { + mSaveScale = MAX_VIDEO_ZOOM_SCALE + scaleFactor = MAX_VIDEO_ZOOM_SCALE / origScale + } else if (mSaveScale < MIN_VIDEO_ZOOM_SCALE) { + mSaveScale = MIN_VIDEO_ZOOM_SCALE + scaleFactor = MIN_VIDEO_ZOOM_SCALE / origScale + } + + mRight = width * mSaveScale - width + mBottom = height * mSaveScale - height + mMatrix.postScale(scaleFactor, scaleFactor, detector.focusX, detector.focusY) + if (scaleFactor < 1) { + mMatrix.getValues(mMatrices) + val y = mMatrices[Matrix.MTRANS_Y] + if (scaleFactor < 1) { + if (y < -mBottom) { + mMatrix.postTranslate(0f, -(y + mBottom)) + } else if (y > 0) { + mMatrix.postTranslate(0f, -y) + } + } + } + return true + } } } 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 6edf32c38..2100ea9ec 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 @@ -8,10 +8,7 @@ import android.content.Intent import android.content.pm.ActivityInfo import android.content.res.Configuration import android.database.Cursor -import android.graphics.Bitmap -import android.graphics.BitmapFactory import android.graphics.Color -import android.graphics.Matrix import android.graphics.drawable.ColorDrawable import android.media.ExifInterface import android.net.Uri @@ -26,7 +23,6 @@ import android.view.WindowManager import android.view.animation.DecelerateInterpolator import android.widget.Toast import androidx.viewpager.widget.ViewPager -import com.bumptech.glide.Glide import com.simplemobiletools.commons.dialogs.PropertiesDialog import com.simplemobiletools.commons.dialogs.RenameItemDialog import com.simplemobiletools.commons.extensions.* @@ -41,6 +37,7 @@ import com.simplemobiletools.gallery.pro.dialogs.SaveAsDialog import com.simplemobiletools.gallery.pro.dialogs.SlideshowDialog import com.simplemobiletools.gallery.pro.extensions.* import com.simplemobiletools.gallery.pro.fragments.PhotoFragment +import com.simplemobiletools.gallery.pro.fragments.VideoFragment import com.simplemobiletools.gallery.pro.fragments.ViewPagerFragment import com.simplemobiletools.gallery.pro.helpers.* import com.simplemobiletools.gallery.pro.models.Medium @@ -48,9 +45,6 @@ import com.simplemobiletools.gallery.pro.models.ThumbnailItem import kotlinx.android.synthetic.main.activity_medium.* import kotlinx.android.synthetic.main.bottom_actions.* import java.io.File -import java.io.FileOutputStream -import java.io.InputStream -import java.io.OutputStream import java.util.* class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, ViewPagerFragment.FragmentListener { @@ -305,7 +299,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View view_pager.onGlobalLayout { Handler().postDelayed({ fragmentClicked() - }, 500) + }, HIDE_SYSTEM_UI_DELAY) } } @@ -492,6 +486,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View swipeToNextMedium() } }, mSlideshowInterval * 1000L) + } else { + (getCurrentFragment() as? VideoFragment)!!.playVideo() } } } @@ -502,7 +498,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View private fun getMediaForSlideshow(): Boolean { mSlideshowMedia = mMediaFiles.filter { - it.isImage() || (config.slideshowIncludeGIFs && it.isGIF()) + it.isImage() || (config.slideshowIncludeVideos && it.isVideo() || (config.slideshowIncludeGIFs && it.isGIF())) }.toMutableList() if (config.slideshowRandomOrder) { @@ -591,111 +587,18 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View val currPath = getCurrentPath() SaveAsDialog(this, currPath, false) { handleSAFDialog(it) { + toast(R.string.saving) Thread { - saveImageToFile(currPath, it) + saveRotatedImageToFile(currPath, it, mRotationDegrees) { + toast(R.string.file_saved) + mRotationDegrees = 0 + invalidateOptionsMenu() + } }.start() } } } - private fun saveImageToFile(oldPath: String, newPath: String) { - toast(R.string.saving) - if (oldPath == newPath && oldPath.isJpg()) { - if (tryRotateByExif(oldPath)) { - return - } - } - - val tmpPath = "$recycleBinPath/.tmp_${newPath.getFilenameFromPath()}" - val tmpFileDirItem = FileDirItem(tmpPath, tmpPath.getFilenameFromPath()) - try { - getFileOutputStream(tmpFileDirItem) { - if (it == null) { - toast(R.string.unknown_error_occurred) - return@getFileOutputStream - } - - val oldLastModified = getCurrentFile().lastModified() - if (oldPath.isJpg()) { - copyFile(getCurrentPath(), tmpPath) - saveExifRotation(ExifInterface(tmpPath), mRotationDegrees) - } else { - val inputstream = getFileInputStreamSync(oldPath) - val bitmap = BitmapFactory.decodeStream(inputstream) - saveFile(tmpPath, bitmap, it as FileOutputStream) - } - - if (getDoesFilePathExist(newPath)) { - tryDeleteFileDirItem(FileDirItem(newPath, newPath.getFilenameFromPath()), false, true) - } - - copyFile(tmpPath, newPath) - scanPathRecursively(newPath) - toast(R.string.file_saved) - - if (config.keepLastModified) { - File(newPath).setLastModified(oldLastModified) - updateLastModified(newPath, oldLastModified) - } - - it.flush() - it.close() - mRotationDegrees = 0 - invalidateOptionsMenu() - - // we cannot refresh a specific image in Glide Cache, so just clear it all - val glide = Glide.get(applicationContext) - glide.clearDiskCache() - runOnUiThread { - glide.clearMemory() - } - } - } catch (e: OutOfMemoryError) { - toast(R.string.out_of_memory_error) - } catch (e: Exception) { - showErrorToast(e) - } finally { - tryDeleteFileDirItem(tmpFileDirItem, false, true) - } - } - - @TargetApi(Build.VERSION_CODES.N) - private fun tryRotateByExif(path: String): Boolean { - return try { - if (saveImageRotation(path, mRotationDegrees)) { - mRotationDegrees = 0 - invalidateOptionsMenu() - toast(R.string.file_saved) - true - } else { - false - } - } catch (e: Exception) { - showErrorToast(e) - false - } - } - - private fun copyFile(source: String, destination: String) { - var inputStream: InputStream? = null - var out: OutputStream? = null - try { - out = getFileOutputStreamSync(destination, source.getMimeType()) - inputStream = getFileInputStreamSync(source) - inputStream?.copyTo(out!!) - } finally { - inputStream?.close() - out?.close() - } - } - - private fun saveFile(path: String, bitmap: Bitmap, out: FileOutputStream) { - val matrix = Matrix() - matrix.postRotate(mRotationDegrees.toFloat()) - val bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) - bmp.compress(path.getCompressionFormat(), 90, out) - } - private fun isShowHiddenFlagNeeded(): Boolean { val file = File(mPath) if (file.isHidden) { @@ -1160,8 +1063,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View private fun getCurrentPath() = getCurrentMedium()?.path ?: "" - private fun getCurrentFile() = File(getCurrentPath()) - override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} override fun onPageSelected(position: Int) { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt index 0206d451e..ef0f82aea 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt @@ -1,11 +1,7 @@ package com.simplemobiletools.gallery.pro.adapters -import android.content.ContentProviderOperation -import android.media.ExifInterface -import android.media.MediaMetadataRetriever import android.os.Handler import android.os.Looper -import android.provider.MediaStore import android.view.Menu import android.view.View import android.view.ViewGroup @@ -32,7 +28,6 @@ import com.simplemobiletools.gallery.pro.models.ThumbnailItem import com.simplemobiletools.gallery.pro.models.ThumbnailSection import kotlinx.android.synthetic.main.photo_video_item_grid.view.* import kotlinx.android.synthetic.main.thumbnail_section.view.* -import java.text.SimpleDateFormat import java.util.* class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList, val listener: MediaOperationsListener?, val isAGetIntent: Boolean, @@ -41,7 +36,6 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList toggleFavorites(false) R.id.cab_restore_recycle_bin_files -> restoreFiles() R.id.cab_share -> shareMedia() + R.id.cab_rotate_right -> rotateSelection(90) + R.id.cab_rotate_left -> rotateSelection(270) + R.id.cab_rotate_one_eighty -> rotateSelection(180) R.id.cab_copy_to -> copyMoveTo(true) R.id.cab_move_to -> moveFilesTo() R.id.cab_select_all -> selectAll() @@ -278,6 +275,25 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList() - val mediumDao = activity.galleryDB.MediumDao() - val paths = getSelectedPaths() - for (path in paths) { - val dateTime = ExifInterface(path).getAttribute(ExifInterface.TAG_DATETIME_ORIGINAL) - ?: ExifInterface(path).getAttribute(ExifInterface.TAG_DATETIME) ?: continue - - // some formats contain a "T" in the middle, some don't - // sample dates: 2015-07-26T14:55:23, 2018:09:05 15:09:05 - val t = if (dateTime.substring(10, 11) == "T") "\'T\'" else " " - val separator = dateTime.substring(4, 5) - val format = "yyyy${separator}MM${separator}dd${t}kk:mm:ss" - val formatter = SimpleDateFormat(format, Locale.getDefault()) - val timestamp = formatter.parse(dateTime).time - - val uri = activity.getFileUri(path) - ContentProviderOperation.newUpdate(uri).apply { - val selection = "${MediaStore.Images.Media.DATA} = ?" - val selectionArgs = arrayOf(path) - withSelection(selection, selectionArgs) - withValue(MediaStore.Images.Media.DATE_TAKEN, timestamp) - operations.add(build()) - } - - if (operations.size % BATCH_SIZE == 0) { - activity.contentResolver.applyBatch(MediaStore.AUTHORITY, operations) - operations.clear() - } - - mediumDao.updateFavoriteDateTaken(path, timestamp) - didUpdateFile = true - } - - val resultSize = activity.contentResolver.applyBatch(MediaStore.AUTHORITY, operations).size - if (resultSize == 0) { - didUpdateFile = false - activity.rescanPaths(paths) - } - - activity.toast(if (didUpdateFile) R.string.dates_fixed_successfully else R.string.unknown_error_occurred) - activity.runOnUiThread { - listener?.refreshItems() - finishActMode() - } - } catch (e: Exception) { - activity.showErrorToast(e) + activity.fixDateTaken(getSelectedPaths()) { + listener?.refreshItems() + finishActMode() } }.start() } @@ -515,13 +485,4 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList Unit activity.hideKeyboard(v) } + include_videos_holder.setOnClickListener { + interval_value.clearFocus() + include_videos.toggle() + } + include_gifs_holder.setOnClickListener { interval_value.clearFocus() include_gifs.toggle() @@ -74,6 +79,7 @@ class SlideshowDialog(val activity: BaseSimpleActivity, val callback: () -> Unit val config = activity.config view.apply { interval_value.setText(config.slideshowInterval.toString()) + include_videos.isChecked = config.slideshowIncludeVideos include_gifs.isChecked = config.slideshowIncludeGIFs random_order.isChecked = config.slideshowRandomOrder use_fade.isChecked = config.slideshowUseFade @@ -89,6 +95,7 @@ class SlideshowDialog(val activity: BaseSimpleActivity, val callback: () -> Unit activity.config.apply { slideshowInterval = interval.toInt() + slideshowIncludeVideos = view.include_videos.isChecked slideshowIncludeGIFs = view.include_gifs.isChecked slideshowRandomOrder = view.random_order.isChecked slideshowUseFade = view.use_fade.isChecked 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 1c66fdf2b..d6b730259 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 @@ -1,11 +1,19 @@ package com.simplemobiletools.gallery.pro.extensions +import android.annotation.TargetApi import android.app.Activity +import android.content.ContentProviderOperation import android.content.Intent +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Matrix +import android.media.ExifInterface +import android.os.Build import android.provider.MediaStore import android.util.DisplayMetrics import android.view.View import androidx.appcompat.app.AppCompatActivity +import com.bumptech.glide.Glide import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.extensions.* @@ -19,9 +27,12 @@ import com.simplemobiletools.gallery.pro.dialogs.PickDirectoryDialog import com.simplemobiletools.gallery.pro.helpers.NOMEDIA import com.simplemobiletools.gallery.pro.helpers.RECYCLE_BIN import com.simplemobiletools.gallery.pro.interfaces.MediumDao +import com.squareup.picasso.Picasso import java.io.File +import java.io.FileOutputStream import java.io.InputStream import java.io.OutputStream +import java.text.SimpleDateFormat import java.util.* fun Activity.sharePath(path: String) { @@ -48,8 +59,8 @@ fun Activity.openPath(path: String, forceChooser: Boolean) { openPathIntent(path, forceChooser, BuildConfig.APPLICATION_ID) } -fun Activity.openEditor(path: String) { - openEditorIntent(path, BuildConfig.APPLICATION_ID) +fun Activity.openEditor(path: String, forceChooser: Boolean = false) { + openEditorIntent(path, forceChooser, BuildConfig.APPLICATION_ID) } fun Activity.launchCamera() { @@ -70,7 +81,7 @@ fun SimpleActivity.launchAbout() { FAQItem(R.string.faq_1_title, R.string.faq_1_text), FAQItem(R.string.faq_2_title, R.string.faq_2_text), FAQItem(R.string.faq_3_title, R.string.faq_3_text), - FAQItem(R.string.faq_4_title, R.string.faq_4_text_old), + FAQItem(R.string.faq_4_title, R.string.faq_4_text), FAQItem(R.string.faq_5_title, R.string.faq_5_text), FAQItem(R.string.faq_6_title, R.string.faq_6_text), FAQItem(R.string.faq_7_title, R.string.faq_7_text), @@ -233,6 +244,7 @@ fun BaseSimpleActivity.restoreRecycleBinPath(path: String, callback: () -> Unit) fun BaseSimpleActivity.restoreRecycleBinPaths(paths: ArrayList, mediumDao: MediumDao = galleryDB.MediumDao(), callback: () -> Unit) { Thread { + val newPaths = ArrayList() paths.forEach { val source = it val destination = it.removePrefix(recycleBinPath) @@ -246,6 +258,7 @@ fun BaseSimpleActivity.restoreRecycleBinPaths(paths: ArrayList, mediumDa if (File(source).length() == File(destination).length()) { mediumDao.updateDeleted(destination.removePrefix(recycleBinPath), 0, "$RECYCLE_BIN$destination") } + newPaths.add(destination) } catch (e: Exception) { showErrorToast(e) } finally { @@ -257,6 +270,8 @@ fun BaseSimpleActivity.restoreRecycleBinPaths(paths: ArrayList, mediumDa runOnUiThread { callback() } + + fixDateTaken(newPaths) }.start() } @@ -305,3 +320,156 @@ fun Activity.hasNavBar(): Boolean { return (realDisplayMetrics.widthPixels - displayMetrics.widthPixels > 0) || (realDisplayMetrics.heightPixels - displayMetrics.heightPixels > 0) } + +fun Activity.fixDateTaken(paths: ArrayList, callback: (() -> Unit)? = null) { + val BATCH_SIZE = 50 + toast(R.string.fixing) + try { + var didUpdateFile = false + val operations = ArrayList() + val mediumDao = galleryDB.MediumDao() + for (path in paths) { + val dateTime = ExifInterface(path).getAttribute(ExifInterface.TAG_DATETIME_ORIGINAL) + ?: ExifInterface(path).getAttribute(ExifInterface.TAG_DATETIME) ?: continue + + // some formats contain a "T" in the middle, some don't + // sample dates: 2015-07-26T14:55:23, 2018:09:05 15:09:05 + val t = if (dateTime.substring(10, 11) == "T") "\'T\'" else " " + val separator = dateTime.substring(4, 5) + val format = "yyyy${separator}MM${separator}dd${t}kk:mm:ss" + val formatter = SimpleDateFormat(format, Locale.getDefault()) + val timestamp = formatter.parse(dateTime).time + + val uri = getFileUri(path) + ContentProviderOperation.newUpdate(uri).apply { + val selection = "${MediaStore.Images.Media.DATA} = ?" + val selectionArgs = arrayOf(path) + withSelection(selection, selectionArgs) + withValue(MediaStore.Images.Media.DATE_TAKEN, timestamp) + operations.add(build()) + } + + if (operations.size % BATCH_SIZE == 0) { + contentResolver.applyBatch(MediaStore.AUTHORITY, operations) + operations.clear() + } + + mediumDao.updateFavoriteDateTaken(path, timestamp) + didUpdateFile = true + } + + val resultSize = contentResolver.applyBatch(MediaStore.AUTHORITY, operations).size + if (resultSize == 0) { + didUpdateFile = false + rescanPaths(paths) + } + + toast(if (didUpdateFile) R.string.dates_fixed_successfully else R.string.unknown_error_occurred) + runOnUiThread { + callback?.invoke() + } + } catch (e: Exception) { + showErrorToast(e) + } +} + +fun BaseSimpleActivity.saveRotatedImageToFile(oldPath: String, newPath: String, degrees: Int, callback: () -> Unit) { + if (oldPath == newPath && oldPath.isJpg()) { + if (tryRotateByExif(oldPath, degrees, callback)) { + return + } + } + + val tmpPath = "$recycleBinPath/.tmp_${newPath.getFilenameFromPath()}" + val tmpFileDirItem = FileDirItem(tmpPath, tmpPath.getFilenameFromPath()) + try { + getFileOutputStream(tmpFileDirItem) { + if (it == null) { + toast(R.string.unknown_error_occurred) + return@getFileOutputStream + } + + val oldLastModified = File(oldPath).lastModified() + if (oldPath.isJpg()) { + copyFile(oldPath, tmpPath) + saveExifRotation(ExifInterface(tmpPath), degrees) + } else { + val inputstream = getFileInputStreamSync(oldPath) + val bitmap = BitmapFactory.decodeStream(inputstream) + saveFile(tmpPath, bitmap, it as FileOutputStream, degrees) + } + + if (getDoesFilePathExist(newPath)) { + tryDeleteFileDirItem(FileDirItem(newPath, newPath.getFilenameFromPath()), false, true) + } + + copyFile(tmpPath, newPath) + scanPathRecursively(newPath) + fileRotatedSuccessfully(newPath, oldLastModified) + + it.flush() + it.close() + callback.invoke() + } + } catch (e: OutOfMemoryError) { + toast(R.string.out_of_memory_error) + } catch (e: Exception) { + showErrorToast(e) + } finally { + tryDeleteFileDirItem(tmpFileDirItem, false, true) + } +} + +@TargetApi(Build.VERSION_CODES.N) +fun Activity.tryRotateByExif(path: String, degrees: Int, callback: () -> Unit): Boolean { + return try { + val file = File(path) + val oldLastModified = file.lastModified() + if (saveImageRotation(path, degrees)) { + fileRotatedSuccessfully(path, oldLastModified) + callback.invoke() + toast(R.string.file_saved) + true + } else { + false + } + } catch (e: Exception) { + showErrorToast(e) + false + } +} + +fun Activity.fileRotatedSuccessfully(path: String, lastModified: Long) { + if (config.keepLastModified) { + File(path).setLastModified(lastModified) + updateLastModified(path, lastModified) + } + + Picasso.get().invalidate(path.getFileKey()) + // we cannot refresh a specific image in Glide Cache, so just clear it all + val glide = Glide.get(applicationContext) + glide.clearDiskCache() + runOnUiThread { + glide.clearMemory() + } +} + +fun BaseSimpleActivity.copyFile(source: String, destination: String) { + var inputStream: InputStream? = null + var out: OutputStream? = null + try { + out = getFileOutputStreamSync(destination, source.getMimeType()) + inputStream = getFileInputStreamSync(source) + inputStream?.copyTo(out!!) + } finally { + inputStream?.close() + out?.close() + } +} + +fun saveFile(path: String, bitmap: Bitmap, out: FileOutputStream, degrees: Int) { + val matrix = Matrix() + matrix.postRotate(degrees.toFloat()) + val bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) + bmp.compress(path.getCompressionFormat(), 90, out) +} 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 ee08503bf..3941ba0db 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 @@ -6,9 +6,11 @@ import com.simplemobiletools.commons.helpers.OTG_PATH import java.io.File import java.io.IOException -fun String.getFileSignature(): ObjectKey { +fun String.getFileSignature() = ObjectKey(getFileKey()) + +fun String.getFileKey(): String { val file = File(this) - return ObjectKey("${file.absolutePath}${file.lastModified()}") + return "${file.absolutePath}${file.lastModified()}" } fun String.isThisOrParentIncluded(includedPaths: MutableSet) = includedPaths.any { startsWith(it, true) } @@ -21,6 +23,8 @@ fun String.shouldFolderBeVisible(excludedPaths: MutableSet, includedPath false } else if (!showHidden && file.containsNoMedia()) { false + } else if (excludedPaths.contains(this) && !includedPaths.contains(this)) { + false } else if (isThisOrParentIncluded(includedPaths)) { true } else if (isThisOrParentExcluded(excludedPaths)) { 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 f8a36a11b..49cdabda3 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 @@ -2,10 +2,7 @@ package com.simplemobiletools.gallery.pro.fragments import android.content.Intent import android.content.res.Configuration -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import android.graphics.Color -import android.graphics.Matrix +import android.graphics.* import android.graphics.drawable.ColorDrawable import android.graphics.drawable.PictureDrawable import android.media.ExifInterface.* @@ -106,11 +103,6 @@ class PhotoFragment : ViewPagerFragment() { } if (context.config.allowDownGesture) { - gif_view.setOnTouchListener { v, event -> - handleEvent(event) - false - } - subsampling_view.setOnTouchListener { v, event -> if (mView.subsampling_view.scale == mOriginalSubsamplingScale) { handleEvent(event) @@ -204,6 +196,33 @@ class PhotoFragment : ViewPagerFragment() { storeStateVariables() } + override fun onDestroyView() { + super.onDestroyView() + if (activity?.isDestroyed == false) { + mView.subsampling_view.recycle() + } + mIoadZoomableViewHandler.removeCallbacksAndMessages(null) + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + + // avoid GIFs being skewed, played in wrong aspect ratio + if (mMedium.isGIF()) { + mView.onGlobalLayout { + Handler().postDelayed({ + loadGif() + }, 50) + } + } else { + hideZoomableView() + loadImage() + } + + initExtendedDetails() + updateInstantSwitchWidths() + } + override fun setMenuVisibility(menuVisible: Boolean) { super.setMenuVisibility(menuVisible) mIsFragmentVisible = menuVisible @@ -265,6 +284,7 @@ class PhotoFragment : ViewPagerFragment() { } private fun loadImage() { + checkScreenDimensions() mImageOrientation = getImageOrientation() when { mMedium.isGIF() -> loadGif() @@ -283,8 +303,13 @@ class PhotoFragment : ViewPagerFragment() { } mView.photo_view.beGone() - mView.gif_view.beVisible() - mView.gif_view.setInputSource(source) + val resolution = mMedium.path.getImageResolution() ?: Point(0, 0) + mView.gif_view.apply { + setInputSource(source) + setupGIFView(resolution.x, resolution.y, mScreenWidth, mScreenHeight) { + activity?.supportFinishAfterTransition() + } + } } catch (e: Exception) { loadBitmap() } catch (e: OutOfMemoryError) { @@ -301,7 +326,6 @@ class PhotoFragment : ViewPagerFragment() { } private fun loadBitmap(degrees: Int = 0) { - checkScreenDimensions() var pathToLoad = if (mMedium.path.startsWith("content://")) mMedium.path else "file://${mMedium.path}" pathToLoad = pathToLoad.replace("%", "%25").replace("#", "%23") @@ -309,6 +333,7 @@ class PhotoFragment : ViewPagerFragment() { val picasso = Picasso.get() .load(pathToLoad) .centerInside() + .stableKey(mMedium.path.getFileKey()) .resize(mScreenWidth, mScreenHeight) if (degrees != 0) { @@ -537,33 +562,6 @@ class PhotoFragment : ViewPagerFragment() { } } - override fun onDestroyView() { - super.onDestroyView() - if (activity?.isDestroyed == false) { - mView.subsampling_view.recycle() - } - mIoadZoomableViewHandler.removeCallbacksAndMessages(null) - } - - override fun onConfigurationChanged(newConfig: Configuration) { - super.onConfigurationChanged(newConfig) - - // avoid GIFs being skewed, played in wrong aspect ratio - if (mMedium.isGIF()) { - mView.onGlobalLayout { - Handler().postDelayed({ - loadGif() - }, 50) - } - } else { - hideZoomableView() - loadImage() - } - - initExtendedDetails() - updateInstantSwitchWidths() - } - private fun hideZoomableView() { if (context?.config?.allowZoomingImages == true) { mIsSubsamplingVisible = false 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 0ef8a6223..beebb1604 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 @@ -2,56 +2,131 @@ package com.simplemobiletools.gallery.pro.fragments import android.content.Intent import android.content.res.Configuration +import android.graphics.Matrix +import android.graphics.Point +import android.graphics.SurfaceTexture +import android.net.Uri import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.os.Handler +import android.util.DisplayMetrics +import android.view.* +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.SeekBar +import android.widget.TextView import com.bumptech.glide.Glide +import com.google.android.exoplayer2.* +import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory +import com.google.android.exoplayer2.source.ExtractorMediaSource +import com.google.android.exoplayer2.source.TrackGroupArray +import com.google.android.exoplayer2.trackselection.TrackSelectionArray +import com.google.android.exoplayer2.upstream.ContentDataSource +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.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.MEDIUM -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.* import kotlinx.android.synthetic.main.pager_video_item.view.* import java.io.File import java.io.FileInputStream -class VideoFragment : ViewPagerFragment() { +class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, SeekBar.OnSeekBarChangeListener { + private val PROGRESS = "progress" + private var mIsFullscreen = false private var mWasFragmentInit = false private var mIsPanorama = false + private var mIsFragmentVisible = false + private var mIsPlaying = false + private var mIsDragged = false + private var mWasVideoStarted = false + private var mCurrTime = 0 + private var mDuration = 0 + private var mSaveScale = 1f + private var mRight = 0f + private var mBottom = 0f + private var mLastTouchX = 0f + private var mLastTouchY = 0f + private var mCurrZoomMode = ZOOM_MODE_NONE + + private var mExoPlayer: SimpleExoPlayer? = null + private var mVideoSize = Point(0, 0) + private var mTimerHandler = Handler() + private var mScaleDetector: ScaleGestureDetector? = null + private var mMatrices = FloatArray(9) + private val mMatrix = Matrix() private var mStoredShowExtendedDetails = false private var mStoredHideExtendedDetails = false private var mStoredBottomActions = true private var mStoredExtendedDetails = 0 + private var mStoredRememberLastVideoPosition = false + private var mStoredLastVideoPath = "" + private var mStoredLastVideoPosition = 0 + private lateinit var mTimeHolder: View private lateinit var mBrightnessSideScroll: MediaSideScroll private lateinit var mVolumeSideScroll: MediaSideScroll - private lateinit var mView: View private lateinit var mMedium: Medium + private lateinit var mConfig: Config + private lateinit var mTextureView: TextureView + private lateinit var mCurrTimeView: TextView + private lateinit var mPlayPauseButton: ImageView + private lateinit var mSeekBar: SeekBar override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + mConfig = context!!.config + mScaleDetector = ScaleGestureDetector(context, ScaleListener()) mView = inflater.inflate(R.layout.pager_video_item, container, false).apply { instant_prev_item.setOnClickListener { listener?.goToPrevItem() } instant_next_item.setOnClickListener { listener?.goToNextItem() } + video_curr_time.setOnClickListener { skip(false) } + video_duration.setOnClickListener { skip(true) } video_holder.setOnClickListener { toggleFullscreen() } video_preview.setOnClickListener { toggleFullscreen() } panorama_outline.setOnClickListener { openPanorama() } - video_play_outline.setOnClickListener { launchVideoPlayer() } + video_play_outline.setOnClickListener { + if (mConfig.openVideosOnSeparateScreen) { + launchVideoPlayer() + } else { + togglePlayPause() + } + } + mPlayPauseButton = video_toggle_play_pause + mPlayPauseButton.setOnClickListener { + togglePlayPause() + } + + mSeekBar = video_seekbar + mSeekBar.setOnSeekBarChangeListener(this@VideoFragment) + // adding an empty click listener just to avoid ripple animation at toggling fullscreen + mSeekBar.setOnClickListener { } + + mTimeHolder = video_time_holder + mCurrTimeView = video_curr_time mBrightnessSideScroll = video_brightness_controller mVolumeSideScroll = video_volume_controller + mTextureView = video_surface - if (context.config.allowDownGesture) { - video_preview.setOnTouchListener { v, event -> + if (mConfig.allowDownGesture) { + video_preview.setOnTouchListener { view, event -> handleEvent(event) false } + + video_surface.setOnTouchListener { view, event -> + handleEventWithZooming(event) + true + } } } @@ -59,9 +134,20 @@ class VideoFragment : ViewPagerFragment() { 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) + if (!mIsFragmentVisible && activity is VideoActivity) { + mIsFragmentVisible = true + } + mIsFullscreen = activity!!.window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_FULLSCREEN == View.SYSTEM_UI_FLAG_FULLSCREEN + initTimeHolder() checkIfPanorama() + mMedium.path.getVideoResolution()?.apply { + mVideoSize.x = x + mVideoSize.y = y + } + if (mIsPanorama) { mView.apply { panorama_outline.beVisible() @@ -73,8 +159,17 @@ class VideoFragment : ViewPagerFragment() { } if (!mIsPanorama) { + setupPlayer() + if (savedInstanceState != null) { + mCurrTime = savedInstanceState.getInt(PROGRESS) + } + mWasFragmentInit = true + if (mVideoSize.x != 0 && mVideoSize.y != 0) { + setVideoSize() + } + mView.apply { mBrightnessSideScroll.initialize(activity!!, slide_info, true, container) { x, y -> video_holder.performClick() @@ -83,19 +178,31 @@ class VideoFragment : ViewPagerFragment() { mVolumeSideScroll.initialize(activity!!, slide_info, false, container) { x, y -> video_holder.performClick() } + + video_surface.onGlobalLayout { + if (mIsFragmentVisible && mConfig.autoplayVideos && !mConfig.openVideosOnSeparateScreen) { + playVideo() + } + } } } + setupVideoDuration() + if (mStoredRememberLastVideoPosition) { + setLastVideoSavedPosition() + } + updateInstantSwitchWidths() return mView } override fun onResume() { super.onResume() + mConfig = context!!.config // make sure we get a new config, in case the user changed something in the app settings activity!!.updateTextColors(mView.video_holder) - val config = context!!.config - val allowVideoGestures = config.allowVideoGestures - val allowInstantChange = config.allowInstantChange + val allowVideoGestures = mConfig.allowVideoGestures + val allowInstantChange = mConfig.allowInstantChange + mTextureView.beGoneIf(mConfig.openVideosOnSeparateScreen || mIsPanorama) mView.apply { video_volume_controller.beVisibleIf(allowVideoGestures && !mIsPanorama) video_brightness_controller.beVisibleIf(allowVideoGestures && !mIsPanorama) @@ -105,29 +212,174 @@ class VideoFragment : ViewPagerFragment() { } checkExtendedDetails() + initTimeHolder() storeStateVariables() } override fun onPause() { super.onPause() storeStateVariables() + pauseVideo() + if (mStoredRememberLastVideoPosition && mIsFragmentVisible && mWasVideoStarted) { + saveVideoProgress() + } + } + + override fun onDestroy() { + super.onDestroy() + if (activity?.isChangingConfigurations == false) { + cleanup() + } + } + + override fun setMenuVisibility(menuVisible: Boolean) { + super.setMenuVisibility(menuVisible) + if (mIsFragmentVisible && !menuVisible) { + pauseVideo() + } + + mIsFragmentVisible = menuVisible + if (mWasFragmentInit && menuVisible && mConfig.autoplayVideos && !mConfig.openVideosOnSeparateScreen) { + playVideo() + } } override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) + setVideoSize() + initTimeHolder() checkExtendedDetails() updateInstantSwitchWidths() } + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + outState.putInt(PROGRESS, mCurrTime) + } + + private fun storeStateVariables() { - context!!.config.apply { + mConfig.apply { mStoredShowExtendedDetails = showExtendedDetails mStoredHideExtendedDetails = hideExtendedDetails mStoredExtendedDetails = extendedDetails mStoredBottomActions = bottomActions + mStoredRememberLastVideoPosition = rememberLastVideoPosition + mStoredLastVideoPath = lastVideoPath + mStoredLastVideoPosition = lastVideoPosition } } + private fun setupPlayer() { + if (activity == null || mConfig.openVideosOnSeparateScreen || mIsPanorama) { + return + } + + mTextureView.setOnClickListener { toggleFullscreen() } + mTextureView.surfaceTextureListener = this + + checkExtendedDetails() + + mExoPlayer = ExoPlayerFactory.newSimpleInstance(context) + mExoPlayer!!.seekParameters = SeekParameters.CLOSEST_SYNC + initExoPlayerListeners() + } + + private fun saveVideoProgress() { + if (!videoEnded()) { + mStoredLastVideoPosition = mExoPlayer!!.currentPosition.toInt() / 1000 + mStoredLastVideoPath = mMedium.path + } + + mConfig.apply { + lastVideoPosition = mStoredLastVideoPosition + lastVideoPath = mStoredLastVideoPath + } + } + + private fun setLastVideoSavedPosition() { + if (mStoredLastVideoPath == mMedium.path && mStoredLastVideoPosition > 0) { + setPosition(mStoredLastVideoPosition) + } + } + + private fun setupTimeHolder() { + mSeekBar.max = mDuration + mView.video_duration.text = mDuration.getFormattedDuration() + setupTimer() + } + + private fun setupTimer() { + activity!!.runOnUiThread(object : Runnable { + override fun run() { + if (mExoPlayer != null && !mIsDragged && mIsPlaying) { + mCurrTime = (mExoPlayer!!.currentPosition / 1000).toInt() + mSeekBar.progress = mCurrTime + mCurrTimeView.text = mCurrTime.getFormattedDuration() + } + + mTimerHandler.postDelayed(this, 1000) + } + }) + } + + private fun initExoPlayer() { + val isContentUri = mMedium.path.startsWith("content://") + val uri = if (isContentUri) Uri.parse(mMedium.path) else Uri.fromFile(File(mMedium.path)) + val dataSpec = DataSpec(uri) + val fileDataSource = if (isContentUri) ContentDataSource(context) else FileDataSource() + try { + fileDataSource.open(dataSpec) + } catch (e: Exception) { + activity?.showErrorToast(e) + } + + val factory = DataSource.Factory { fileDataSource } + val audioSource = ExtractorMediaSource(fileDataSource.uri, factory, DefaultExtractorsFactory(), null, null) + mExoPlayer!!.audioStreamType = C.STREAM_TYPE_MUSIC + mExoPlayer!!.prepare(audioSource) + } + + private fun initExoPlayerListeners() { + mExoPlayer!!.addListener(object : Player.EventListener { + override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {} + + override fun onSeekProcessed() {} + + override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) {} + + override fun onPlayerError(error: ExoPlaybackException?) { + } + + override fun onLoadingChanged(isLoading: Boolean) {} + + override fun onPositionDiscontinuity(reason: Int) {} + + override fun onRepeatModeChanged(repeatMode: Int) {} + + override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {} + + override fun onTimelineChanged(timeline: Timeline?, manifest: Any?, reason: Int) {} + + override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) { + when (playbackState) { + Player.STATE_READY -> videoPrepared() + Player.STATE_ENDED -> videoCompleted() + } + } + }) + + mExoPlayer!!.addVideoListener(object : SimpleExoPlayer.VideoListener { + override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) { + mVideoSize.x = width + mVideoSize.y = height + setVideoSize() + } + + override fun onRenderedFirstFrame() {} + }) + } + private fun launchVideoPlayer() { listener?.launchViewVideoIntent(mMedium.path) } @@ -137,7 +389,7 @@ class VideoFragment : ViewPagerFragment() { } private fun checkExtendedDetails() { - if (context!!.config.showExtendedDetails) { + if (mConfig.showExtendedDetails) { mView.video_details.apply { beInvisible() // make it invisible so we can measure it, but not show yet text = getMediumExtendedDetails(mMedium) @@ -147,7 +399,7 @@ class VideoFragment : ViewPagerFragment() { if (realY > 0) { y = realY beVisibleIf(text.isNotEmpty()) - alpha = if (!context!!.config.hideExtendedDetails || !mIsFullscreen) 1f else 0f + alpha = if (!mConfig.hideExtendedDetails || !mIsFullscreen) 1f else 0f } } } @@ -157,11 +409,31 @@ class VideoFragment : ViewPagerFragment() { } } + private fun initTimeHolder() { + var right = 0 + var bottom = context!!.navigationBarHeight + if (mConfig.bottomActions) { + bottom += resources.getDimension(R.dimen.bottom_actions_height).toInt() + } + + if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && activity?.hasNavBar() == true) { + right += activity!!.navigationBarWidth + } + + (mTimeHolder.layoutParams as RelativeLayout.LayoutParams).apply { + bottomMargin = bottom + rightMargin = right + } + mTimeHolder.beInvisibleIf(mIsFullscreen) + } + private fun checkIfPanorama() { try { val fis = FileInputStream(File(mMedium.path)) - context!!.parseFileChannel(mMedium.path, fis.channel, 0, 0, 0) { - mIsPanorama = true + fis.use { fis -> + context!!.parseFileChannel(mMedium.path, fis.channel, 0, 0, 0) { + mIsPanorama = true + } } } catch (ignored: Exception) { } catch (ignored: OutOfMemoryError) { @@ -183,12 +455,23 @@ class VideoFragment : ViewPagerFragment() { override fun fullscreenToggled(isFullscreen: Boolean) { mIsFullscreen = isFullscreen + val newAlpha = if (isFullscreen) 0f else 1f + if (!mIsFullscreen) { + mTimeHolder.beVisible() + } + + mSeekBar.setOnSeekBarChangeListener(if (mIsFullscreen) null else this) + arrayOf(mView.video_curr_time, mView.video_duration).forEach { + it.isClickable = !mIsFullscreen + } + + mTimeHolder.animate().alpha(newAlpha).start() mView.video_details.apply { if (mStoredShowExtendedDetails && isVisible()) { animate().y(getExtendedDetailsY(height)) if (mStoredHideExtendedDetails) { - animate().alpha(if (isFullscreen) 0f else 1f).start() + animate().alpha(newAlpha).start() } } } @@ -197,7 +480,344 @@ class VideoFragment : ViewPagerFragment() { private fun getExtendedDetailsY(height: Int): Float { val smallMargin = resources.getDimension(R.dimen.small_margin) val fullscreenOffset = smallMargin + if (mIsFullscreen) 0 else context!!.navigationBarHeight - val actionsHeight = if (context!!.config.bottomActions && !mIsFullscreen) resources.getDimension(R.dimen.bottom_actions_height) else 0f + var actionsHeight = 0f + if (!mIsFullscreen) { + actionsHeight += resources.getDimension(R.dimen.video_player_play_pause_size) + if (mConfig.bottomActions) { + actionsHeight += resources.getDimension(R.dimen.bottom_actions_height) + } + } return context!!.realScreenSize.y - height - actionsHeight - fullscreenOffset } + + private fun skip(forward: Boolean) { + if (mExoPlayer == null || mIsPanorama) { + return + } + + val curr = mExoPlayer!!.currentPosition + val twoPercents = Math.max((mExoPlayer!!.duration / 50).toInt(), MIN_SKIP_LENGTH) + val newProgress = if (forward) curr + twoPercents else curr - twoPercents + val roundProgress = Math.round(newProgress / 1000f) + val limitedProgress = Math.max(Math.min(mExoPlayer!!.duration.toInt(), roundProgress), 0) + setPosition(limitedProgress) + if (!mIsPlaying) { + togglePlayPause() + } + } + + override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { + if (mExoPlayer != null && fromUser) { + setPosition(progress) + } + } + + override fun onStartTrackingTouch(seekBar: SeekBar) { + if (mExoPlayer == null) + return + + mExoPlayer!!.playWhenReady = false + mIsDragged = true + } + + override fun onStopTrackingTouch(seekBar: SeekBar) { + if (mIsPanorama) { + openPanorama() + return + } + + if (mExoPlayer == null) + return + + if (mIsPlaying) { + mExoPlayer!!.playWhenReady = true + } else { + togglePlayPause() + } + + mIsDragged = false + } + + private fun togglePlayPause() { + if (activity == null || !isAdded) + return + + mIsPlaying = !mIsPlaying + if (mIsPlaying) { + playVideo() + } else { + pauseVideo() + } + } + + fun playVideo() { + if (mExoPlayer == null) { + return + } + + if (mView.video_preview.isVisible()) { + mView.video_preview.beGone() + initExoPlayer() + } + + val wasEnded = videoEnded() + if (wasEnded) { + setPosition(0) + } + + if (mStoredRememberLastVideoPosition) { + setLastVideoSavedPosition() + clearLastVideoSavedProgress() + } + + if (!wasEnded || !mConfig.loopVideos) { + mPlayPauseButton.setImageResource(R.drawable.ic_pause_outline) + } + + if (!mWasVideoStarted) { + mView.video_play_outline.beGone() + mPlayPauseButton.beVisible() + } + + mWasVideoStarted = true + mIsPlaying = true + mExoPlayer?.playWhenReady = true + activity!!.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + + private fun clearLastVideoSavedProgress() { + mStoredLastVideoPosition = 0 + mStoredLastVideoPath = "" + } + + private fun pauseVideo() { + if (mExoPlayer == null) { + return + } + + mIsPlaying = false + if (!videoEnded()) { + mExoPlayer?.playWhenReady = false + } + + mPlayPauseButton.setImageResource(R.drawable.ic_play_outline) + activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + + private fun videoEnded(): Boolean { + val currentPos = mExoPlayer?.currentPosition ?: 0 + val duration = mExoPlayer?.duration ?: 0 + return currentPos != 0L && currentPos >= duration + } + + private fun setPosition(seconds: Int) { + mExoPlayer?.seekTo(seconds * 1000L) + mSeekBar.progress = seconds + mCurrTimeView.text = seconds.getFormattedDuration() + } + + private fun setupVideoDuration() { + mDuration = mMedium.path.getVideoDuration() + setupTimeHolder() + setPosition(0) + } + + private fun videoPrepared() { + if (mDuration == 0) { + mDuration = (mExoPlayer!!.duration / 1000).toInt() + setupTimeHolder() + setPosition(mCurrTime) + + if (mIsFragmentVisible && (mConfig.autoplayVideos)) { + playVideo() + } + } + } + + private fun videoCompleted() { + if (!isAdded || mExoPlayer == null) { + return + } + + mCurrTime = (mExoPlayer!!.duration / 1000).toInt() + if (listener?.videoEnded() == false && mConfig.loopVideos) { + playVideo() + } else { + mSeekBar.progress = mSeekBar.max + mCurrTimeView.text = mDuration.getFormattedDuration() + pauseVideo() + } + } + + private fun cleanup() { + pauseVideo() + releaseExoPlayer() + + if (mWasFragmentInit) { + mCurrTimeView.text = 0.getFormattedDuration() + mSeekBar.progress = 0 + mTimerHandler.removeCallbacksAndMessages(null) + } + } + + private fun releaseExoPlayer() { + mExoPlayer?.stop() + Thread { + mExoPlayer?.release() + mExoPlayer = null + }.start() + } + + override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {} + + override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) {} + + override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?) = false + + override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) { + Thread { + mExoPlayer?.setVideoSurface(Surface(mTextureView.surfaceTexture)) + }.start() + } + + private fun setVideoSize() { + if (activity == null || mConfig.openVideosOnSeparateScreen) { + return + } + + val videoProportion = mVideoSize.x.toFloat() / mVideoSize.y.toFloat() + val display = activity!!.windowManager.defaultDisplay + val screenWidth: Int + val screenHeight: Int + + val realMetrics = DisplayMetrics() + display.getRealMetrics(realMetrics) + screenWidth = realMetrics.widthPixels + screenHeight = realMetrics.heightPixels + + val screenProportion = screenWidth.toFloat() / screenHeight.toFloat() + + mTextureView.layoutParams.apply { + if (videoProportion > screenProportion) { + width = screenWidth + height = (screenWidth.toFloat() / videoProportion).toInt() + } else { + width = (videoProportion * screenHeight.toFloat()).toInt() + height = screenHeight + } + mTextureView.layoutParams = this + } + } + + private fun handleEventWithZooming(event: MotionEvent) { + mScaleDetector?.onTouchEvent(event) + + mMatrix.getValues(mMatrices) + val x = mMatrices[Matrix.MTRANS_X] + val y = mMatrices[Matrix.MTRANS_Y] + + when (event.actionMasked) { + MotionEvent.ACTION_DOWN -> { + mTouchDownTime = System.currentTimeMillis() + mCurrZoomMode = ZOOM_MODE_DRAG + mLastTouchX = event.x + mLastTouchY = event.y + + mTouchDownX = event.x + mTouchDownY = event.y + } + MotionEvent.ACTION_UP -> { + mCurrZoomMode = ZOOM_MODE_NONE + val diffX = mTouchDownX - event.x + val diffY = mTouchDownY - event.y + + if (Math.abs(diffX) < CLICK_MAX_DISTANCE && Math.abs(diffY) < CLICK_MAX_DISTANCE && System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { + mTextureView.performClick() + } else { + val downGestureDuration = System.currentTimeMillis() - mTouchDownTime + if (!mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold && downGestureDuration < MAX_CLOSE_DOWN_GESTURE_DURATION && mSaveScale == 1f) { + activity?.supportFinishAfterTransition() + } + } + mIgnoreCloseDown = false + } + MotionEvent.ACTION_POINTER_DOWN -> { + mLastTouchX = event.x + mLastTouchY = event.y + mCurrZoomMode = ZOOM_MODE_ZOOM + mIgnoreCloseDown = true + } + MotionEvent.ACTION_MOVE -> { + if (mCurrZoomMode == ZOOM_MODE_ZOOM || mCurrZoomMode == ZOOM_MODE_DRAG && mSaveScale > MIN_VIDEO_ZOOM_SCALE) { + var diffX = event.x - mLastTouchX + var diffY = event.y - mLastTouchY + if (y + diffY > 0) { + diffY = -y + } else if (y + diffY < -mBottom) { + diffY = -(y + mBottom) + } + + if (x + diffX > 0) { + diffX = -x + } else if (x + diffX < -mRight) { + diffX = -(x + mRight) + } + + mMatrix.postTranslate(diffX, diffY) + mLastTouchX = event.x + mLastTouchY = event.y + } + } + MotionEvent.ACTION_POINTER_UP -> { + mCurrZoomMode = ZOOM_MODE_NONE + } + } + + mTextureView.setTransform(mMatrix) + mTextureView.invalidate() + } + + // taken from https://github.com/Manuiq/ZoomableTextureView + private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() { + override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { + mCurrZoomMode = ZOOM_MODE_ZOOM + return true + } + + override fun onScale(detector: ScaleGestureDetector): Boolean { + val width = mTextureView.width + val height = mTextureView.height + if (width <= 0 || height <= 0) { + return true + } + + var scaleFactor = detector.scaleFactor + val origScale = mSaveScale + mSaveScale *= scaleFactor + + if (mSaveScale > MAX_VIDEO_ZOOM_SCALE) { + mSaveScale = MAX_VIDEO_ZOOM_SCALE + scaleFactor = MAX_VIDEO_ZOOM_SCALE / origScale + } else if (mSaveScale < MIN_VIDEO_ZOOM_SCALE) { + mSaveScale = MIN_VIDEO_ZOOM_SCALE + scaleFactor = MIN_VIDEO_ZOOM_SCALE / origScale + } + + mRight = width * mSaveScale - width + mBottom = height * mSaveScale - height + mMatrix.postScale(scaleFactor, scaleFactor, detector.focusX, detector.focusY) + if (scaleFactor < 1) { + mMatrix.getValues(mMatrices) + val y = mMatrices[Matrix.MTRANS_Y] + if (scaleFactor < 1) { + if (y < -mBottom) { + mMatrix.postTranslate(0f, -(y + mBottom)) + } else if (y > 0) { + mMatrix.postTranslate(0f, -y) + } + } + } + return true + } + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/ViewPagerFragment.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/ViewPagerFragment.kt index 5153859ad..bee1b525b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/ViewPagerFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/fragments/ViewPagerFragment.kt @@ -13,6 +13,7 @@ import java.io.File abstract class ViewPagerFragment : Fragment() { var listener: FragmentListener? = null + protected var mTouchDownTime = 0L protected var mTouchDownX = 0f protected var mTouchDownY = 0f protected var mCloseDownThreshold = 100f @@ -98,6 +99,7 @@ abstract class ViewPagerFragment : Fragment() { protected fun handleEvent(event: MotionEvent) { when (event.actionMasked) { MotionEvent.ACTION_DOWN -> { + mTouchDownTime = System.currentTimeMillis() mTouchDownX = event.x mTouchDownY = event.y } @@ -106,7 +108,8 @@ abstract class ViewPagerFragment : Fragment() { val diffX = mTouchDownX - event.x val diffY = mTouchDownY - event.y - if (!mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold) { + val downGestureDuration = System.currentTimeMillis() - mTouchDownTime + if (!mIgnoreCloseDown && Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold && downGestureDuration < MAX_CLOSE_DOWN_GESTURE_DURATION) { activity?.supportFinishAfterTransition() } mIgnoreCloseDown = false 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 c218dc78c..29368ae2d 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 @@ -153,7 +153,7 @@ class Config(context: Context) : BaseConfig(context) { set(includedFolders) = prefs.edit().remove(INCLUDED_FOLDERS).putStringSet(INCLUDED_FOLDERS, includedFolders).apply() var autoplayVideos: Boolean - get() = prefs.getBoolean(AUTOPLAY_VIDEOS, true) + get() = prefs.getBoolean(AUTOPLAY_VIDEOS, false) set(autoplay) = prefs.edit().putBoolean(AUTOPLAY_VIDEOS, autoplay).apply() var animateGifs: Boolean @@ -180,6 +180,10 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getBoolean(LOOP_VIDEOS, false) set(loop) = prefs.edit().putBoolean(LOOP_VIDEOS, loop).apply() + var openVideosOnSeparateScreen: Boolean + get() = prefs.getBoolean(OPEN_VIDEOS_ON_SEPARATE_SCREEN, false) + set(openVideosOnSeparateScreen) = prefs.edit().putBoolean(OPEN_VIDEOS_ON_SEPARATE_SCREEN, openVideosOnSeparateScreen).apply() + var displayFileNames: Boolean get() = prefs.getBoolean(DISPLAY_FILE_NAMES, false) set(display) = prefs.edit().putBoolean(DISPLAY_FILE_NAMES, display).apply() @@ -281,6 +285,10 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getInt(SLIDESHOW_INTERVAL, SLIDESHOW_DEFAULT_INTERVAL) set(slideshowInterval) = prefs.edit().putInt(SLIDESHOW_INTERVAL, slideshowInterval).apply() + var slideshowIncludeVideos: Boolean + get() = prefs.getBoolean(SLIDESHOW_INCLUDE_VIDEOS, false) + set(slideshowIncludeVideos) = prefs.edit().putBoolean(SLIDESHOW_INCLUDE_VIDEOS, slideshowIncludeVideos).apply() + var slideshowIncludeGIFs: Boolean get() = prefs.getBoolean(SLIDESHOW_INCLUDE_GIFS, false) set(slideshowIncludeGIFs) = prefs.edit().putBoolean(SLIDESHOW_INCLUDE_GIFS, slideshowIncludeGIFs).apply() @@ -445,4 +453,12 @@ class Config(context: Context) : BaseConfig(context) { var allowOneToOneZoom: Boolean get() = prefs.getBoolean(ALLOW_ONE_TO_ONE_ZOOM, false) set(allowOneToOneZoom) = prefs.edit().putBoolean(ALLOW_ONE_TO_ONE_ZOOM, allowOneToOneZoom).apply() + + var lastEditorDrawColor: Int + get() = prefs.getInt(LAST_EDITOR_DRAW_COLOR, primaryColor) + set(lastEditorDrawColor) = prefs.edit().putInt(LAST_EDITOR_DRAW_COLOR, lastEditorDrawColor).apply() + + var lastEditorBrushSize: Int + get() = prefs.getInt(LAST_EDITOR_BRUSH_SIZE, 50) + set(lastEditorBrushSize) = prefs.edit().putInt(LAST_EDITOR_BRUSH_SIZE, lastEditorBrushSize).apply() } 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 d0c1d72e4..e775ba452 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 @@ -13,6 +13,7 @@ const val IS_THIRD_PARTY_INTENT = "is_third_party_intent" const val AUTOPLAY_VIDEOS = "autoplay_videos" const val REMEMBER_LAST_VIDEO_POSITION = "remember_last_video_position" const val LOOP_VIDEOS = "loop_videos" +const val OPEN_VIDEOS_ON_SEPARATE_SCREEN = "open_videos_on_separate_screen" const val ANIMATE_GIFS = "animate_gifs" const val MAX_BRIGHTNESS = "max_brightness" const val CROP_THUMBNAILS = "crop_thumbnails" @@ -75,9 +76,12 @@ const val LAST_EDITOR_CROP_OTHER_ASPECT_RATIO_Y = "last_editor_crop_other_aspect const val GROUP_DIRECT_SUBFOLDERS = "group_direct_subfolders" const val SHOW_WIDGET_FOLDER_NAME = "show_widget_folder_name" const val ALLOW_ONE_TO_ONE_ZOOM = "allow_one_to_one_zoom" +const val LAST_EDITOR_DRAW_COLOR = "last_editor_draw_color" +const val LAST_EDITOR_BRUSH_SIZE = "last_editor_brush_size" // slideshow 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" @@ -99,9 +103,12 @@ const val GO_TO_PREV_ITEM = "go_to_prev_item" const val MAX_COLUMN_COUNT = 20 const val SHOW_TEMP_HIDDEN_DURATION = 300000L const val CLICK_MAX_DURATION = 150 +const val CLICK_MAX_DISTANCE = 100 +const val MAX_CLOSE_DOWN_GESTURE_DURATION = 400 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 DIRECTORY = "directory" const val MEDIUM = "medium" @@ -177,3 +184,10 @@ const val ASPECT_RATIO_ONE_ONE = 1 const val ASPECT_RATIO_FOUR_THREE = 2 const val ASPECT_RATIO_SIXTEEN_NINE = 3 const val ASPECT_RATIO_OTHER = 4 + +// some constants related to zooming videos +const val MIN_VIDEO_ZOOM_SCALE = 1f +const val MAX_VIDEO_ZOOM_SCALE = 5f +const val ZOOM_MODE_NONE = 0 +const val ZOOM_MODE_DRAG = 1 +const val ZOOM_MODE_ZOOM = 2 diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/PaintOptions.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/PaintOptions.kt new file mode 100644 index 000000000..fc1cacb2a --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/models/PaintOptions.kt @@ -0,0 +1,5 @@ +package com.simplemobiletools.gallery.pro.models + +import android.graphics.Color + +data class PaintOptions(var color: Int = Color.BLACK, var strokeWidth: Float = 5f) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/EditorDrawCanvas.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/EditorDrawCanvas.kt new file mode 100644 index 000000000..592320b33 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/EditorDrawCanvas.kt @@ -0,0 +1,147 @@ +package com.simplemobiletools.gallery.pro.views + +import android.content.Context +import android.graphics.* +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import com.simplemobiletools.gallery.pro.R +import com.simplemobiletools.gallery.pro.extensions.config +import com.simplemobiletools.gallery.pro.models.PaintOptions +import java.util.* + +class EditorDrawCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) { + private var mCurX = 0f + private var mCurY = 0f + private var mStartX = 0f + private var mStartY = 0f + private var mColor = 0 + private var mWasMultitouch = false + + private var mPaths = LinkedHashMap() + private var mPaint = Paint() + private var mPath = Path() + private var mPaintOptions = PaintOptions() + + private var backgroundBitmap: Bitmap? = null + + init { + mColor = context.config.primaryColor + mPaint.apply { + color = mColor + style = Paint.Style.STROKE + strokeJoin = Paint.Join.ROUND + strokeCap = Paint.Cap.ROUND + strokeWidth = 40f + isAntiAlias = true + } + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + canvas.save() + + if (backgroundBitmap != null) { + canvas.drawBitmap(backgroundBitmap!!, 0f, 0f, null) + } + + for ((key, value) in mPaths) { + changePaint(value) + canvas.drawPath(key, mPaint) + } + + changePaint(mPaintOptions) + canvas.drawPath(mPath, mPaint) + canvas.restore() + } + + override fun onTouchEvent(event: MotionEvent): Boolean { + val x = event.x + val y = event.y + + when (event.action and MotionEvent.ACTION_MASK) { + MotionEvent.ACTION_DOWN -> { + mWasMultitouch = false + mStartX = x + mStartY = y + actionDown(x, y) + } + MotionEvent.ACTION_MOVE -> { + if (event.pointerCount == 1 && !mWasMultitouch) { + actionMove(x, y) + } + } + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> actionUp() + MotionEvent.ACTION_POINTER_DOWN -> mWasMultitouch = true + } + + invalidate() + return true + } + + private fun actionDown(x: Float, y: Float) { + mPath.reset() + mPath.moveTo(x, y) + mCurX = x + mCurY = y + } + + private fun actionMove(x: Float, y: Float) { + mPath.quadTo(mCurX, mCurY, (x + mCurX) / 2, (y + mCurY) / 2) + mCurX = x + mCurY = y + } + + private fun actionUp() { + if (!mWasMultitouch) { + mPath.lineTo(mCurX, mCurY) + + // draw a dot on click + if (mStartX == mCurX && mStartY == mCurY) { + mPath.lineTo(mCurX, mCurY + 2) + mPath.lineTo(mCurX + 1, mCurY + 2) + mPath.lineTo(mCurX + 1, mCurY) + } + } + + mPaths[mPath] = mPaintOptions + mPath = Path() + mPaintOptions = PaintOptions(mPaintOptions.color, mPaintOptions.strokeWidth) + } + + private fun changePaint(paintOptions: PaintOptions) { + mPaint.color = paintOptions.color + mPaint.strokeWidth = paintOptions.strokeWidth + } + + fun updateColor(newColor: Int) { + mPaintOptions.color = newColor + } + + fun updateBrushSize(newBrushSize: Int) { + mPaintOptions.strokeWidth = resources.getDimension(R.dimen.full_brush_size) * (newBrushSize / 100f) + } + + fun updateBackgroundBitmap(bitmap: Bitmap) { + backgroundBitmap = bitmap + invalidate() + } + + fun getBitmap(): Bitmap { + val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + canvas.drawColor(Color.WHITE) + draw(canvas) + return bitmap + } + + fun undo() { + if (mPaths.isEmpty()) { + return + } + + val lastKey = mPaths.keys.lastOrNull() + mPaths.remove(lastKey) + invalidate() + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/InstantItemSwitch.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/InstantItemSwitch.kt index c21e2f642..18f2f154e 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/InstantItemSwitch.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/InstantItemSwitch.kt @@ -5,6 +5,7 @@ import android.util.AttributeSet import android.view.MotionEvent import android.view.ViewGroup import android.widget.RelativeLayout +import com.simplemobiletools.gallery.pro.helpers.CLICK_MAX_DISTANCE import com.simplemobiletools.gallery.pro.helpers.CLICK_MAX_DURATION import com.simplemobiletools.gallery.pro.helpers.DRAG_THRESHOLD @@ -40,7 +41,9 @@ class InstantItemSwitch(context: Context, attrs: AttributeSet) : RelativeLayout( mTouchDownTime = System.currentTimeMillis() } MotionEvent.ACTION_UP -> { - if (System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { + val diffX = mTouchDownX - event.x + val diffY = mTouchDownY - event.y + if (Math.abs(diffX) < CLICK_MAX_DISTANCE && Math.abs(diffY) < CLICK_MAX_DISTANCE && System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { performClick() } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/MediaSideScroll.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/MediaSideScroll.kt index 0c424b631..52ebde06e 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/MediaSideScroll.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/MediaSideScroll.kt @@ -13,6 +13,7 @@ import android.widget.TextView import com.simplemobiletools.commons.extensions.onGlobalLayout import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.extensions.audioManager +import com.simplemobiletools.gallery.pro.helpers.CLICK_MAX_DISTANCE import com.simplemobiletools.gallery.pro.helpers.CLICK_MAX_DURATION import com.simplemobiletools.gallery.pro.helpers.DRAG_THRESHOLD @@ -106,7 +107,9 @@ class MediaSideScroll(context: Context, attrs: AttributeSet) : RelativeLayout(co mLastTouchY = event.y } MotionEvent.ACTION_UP -> { - if (System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { + val diffX = mTouchDownX - event.x + val diffY = mTouchDownY - event.y + if (Math.abs(diffX) < CLICK_MAX_DISTANCE && Math.abs(diffY) < CLICK_MAX_DISTANCE && System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { callback(event.rawX, event.rawY) } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/MyZoomableGifTextureView.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/MyZoomableGifTextureView.kt new file mode 100644 index 000000000..be6e23a35 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/views/MyZoomableGifTextureView.kt @@ -0,0 +1,177 @@ +package com.simplemobiletools.gallery.pro.views + +import android.content.Context +import android.graphics.Matrix +import android.graphics.RectF +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.ScaleGestureDetector +import android.widget.ImageView +import com.simplemobiletools.commons.extensions.beVisible +import com.simplemobiletools.gallery.pro.extensions.config +import com.simplemobiletools.gallery.pro.helpers.* +import pl.droidsonroids.gif.GifTextureView + +// allow horizontal swipes through the layout, else it can cause glitches at zoomed in images +class MyZoomableGifTextureView(context: Context, attrs: AttributeSet) : GifTextureView(context, attrs) { + private var mSaveScale = 1f + private var mLastTouchX = 0f + private var mLastTouchY = 0f + private var mTouchDownTime = 0L + private var mTouchDownX = 0f + private var mTouchDownY = 0f + private var mGifWidth = 0f + private var mGifHeight = 0f + private var mScreenWidth = 0f + private var mScreenHeight = 0f + private var mLastFocusX = 0f + private var mLastFocusY = 0f + private var mCloseDownThreshold = 100f + private var mIgnoreCloseDown = false + private var mCurrZoomMode = ZOOM_MODE_NONE + + private var mScaleDetector: ScaleGestureDetector? = null + private var mMatrices = FloatArray(9) + private val mMatrix = Matrix() + private var mCurrentViewport = RectF() + private var mCloseDownCallback: (() -> Unit)? = null + + init { + mScaleDetector = ScaleGestureDetector(context, ScaleListener()) + } + + fun setupGIFView(gifWidth: Int, gifHeight: Int, screenWidth: Int, screenHeight: Int, callback: () -> Unit) { + mCloseDownCallback = callback + // if we don't know the gifs' resolution, just display it and disable zooming + if (gifWidth == 0 || gifHeight == 0) { + scaleType = ImageView.ScaleType.FIT_CENTER + mScaleDetector = null + beVisible() + return + } + + mGifWidth = gifWidth.toFloat() + mGifHeight = gifHeight.toFloat() + mScreenWidth = screenWidth.toFloat() + mScreenHeight = screenHeight.toFloat() + + // we basically want scaleType fitCenter, but we have to use matrices to reach that + val origRect = RectF(0f, 0f, mGifWidth, mGifHeight) + val wantedRect = RectF(0f, 0f, mScreenWidth, mScreenHeight) + mMatrix.setRectToRect(origRect, wantedRect, Matrix.ScaleToFit.CENTER) + mMatrix.getValues(mMatrices) + + val left = mMatrices[Matrix.MTRANS_X] + val top = mMatrices[Matrix.MTRANS_Y] + val right = mScreenWidth - left + val bottom = mScreenHeight - top + mCurrentViewport.set(left, top, right, bottom) + + setTransform(mMatrix) + invalidate() + beVisible() + } + + override fun onTouchEvent(event: MotionEvent): Boolean { + mScaleDetector?.onTouchEvent(event) + + when (event.actionMasked) { + MotionEvent.ACTION_DOWN -> { + mTouchDownTime = System.currentTimeMillis() + mCurrZoomMode = ZOOM_MODE_DRAG + mLastTouchX = event.x + mLastTouchY = event.y + + mTouchDownX = event.x + mTouchDownY = event.y + } + MotionEvent.ACTION_UP -> { + val diffX = mTouchDownX - event.x + val diffY = mTouchDownY - event.y + mCurrZoomMode = ZOOM_MODE_NONE + if (Math.abs(diffX) < CLICK_MAX_DISTANCE && Math.abs(diffY) < CLICK_MAX_DISTANCE && System.currentTimeMillis() - mTouchDownTime < CLICK_MAX_DURATION) { + performClick() + } else { + val downGestureDuration = System.currentTimeMillis() - mTouchDownTime + val areDiffsOK = Math.abs(diffY) > Math.abs(diffX) && diffY < -mCloseDownThreshold + if (mSaveScale == 1f && !mIgnoreCloseDown && areDiffsOK && context.config.allowDownGesture && downGestureDuration < MAX_CLOSE_DOWN_GESTURE_DURATION) { + mCloseDownCallback?.invoke() + } + } + mIgnoreCloseDown = false + } + MotionEvent.ACTION_POINTER_DOWN -> { + mLastTouchX = event.x + mLastTouchY = event.y + mCurrZoomMode = ZOOM_MODE_ZOOM + } + MotionEvent.ACTION_MOVE -> { + if (mCurrZoomMode == ZOOM_MODE_ZOOM || mCurrZoomMode == ZOOM_MODE_DRAG && mSaveScale > MIN_VIDEO_ZOOM_SCALE) { + var diffX = event.x - mLastTouchX + + // horizontal bounds + if (mCurrentViewport.left >= 0) { + diffX = -mCurrentViewport.left + } else if (mCurrentViewport.right + diffX >= mScreenWidth * mSaveScale) { + diffX = -((mScreenWidth * mSaveScale) - mCurrentViewport.right) + } + + mCurrentViewport.left += diffX + mCurrentViewport.right += diffX + + mMatrix.postTranslate(diffX, 0f) + + mCurrentViewport.left = Math.max(mCurrentViewport.left, 0f) + mCurrentViewport.right = Math.min(mCurrentViewport.right, mScreenWidth) + + mLastTouchX = event.x + mLastTouchY = event.y + } + } + MotionEvent.ACTION_POINTER_UP -> { + mCurrZoomMode = ZOOM_MODE_NONE + } + } + + setTransform(mMatrix) + invalidate() + return true + } + + // taken from https://github.com/Manuiq/ZoomableTextureView + private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() { + override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { + mCurrZoomMode = ZOOM_MODE_ZOOM + return true + } + + override fun onScale(detector: ScaleGestureDetector): Boolean { + if (width <= 0 || height <= 0) { + return true + } + + mLastFocusX = detector.focusX + mLastFocusY = detector.focusY + var scaleFactor = detector.scaleFactor + val origScale = mSaveScale + mSaveScale *= scaleFactor + + if (mSaveScale > MAX_VIDEO_ZOOM_SCALE) { + mSaveScale = MAX_VIDEO_ZOOM_SCALE + scaleFactor = MAX_VIDEO_ZOOM_SCALE / origScale + } else if (mSaveScale < MIN_VIDEO_ZOOM_SCALE) { + mSaveScale = MIN_VIDEO_ZOOM_SCALE + scaleFactor = MIN_VIDEO_ZOOM_SCALE / origScale + } + + mMatrix.postScale(scaleFactor, scaleFactor, detector.focusX, detector.focusY) + mMatrix.getValues(mMatrices) + val left = mMatrices[Matrix.MTRANS_X] + val top = mMatrices[Matrix.MTRANS_Y] + val right = mScreenWidth - left + val bottom = mScreenHeight - top + mCurrentViewport.set(left, top, right, bottom) + return true + } + } +} diff --git a/app/src/main/res/drawable-hdpi/ic_draw.png b/app/src/main/res/drawable-hdpi/ic_draw.png new file mode 100644 index 000000000..b2c513174 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_draw.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_draw.png b/app/src/main/res/drawable-xhdpi/ic_draw.png new file mode 100644 index 000000000..534bf7180 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_draw.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_draw.png b/app/src/main/res/drawable-xxhdpi/ic_draw.png new file mode 100644 index 000000000..3e42d0923 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_draw.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_draw.png b/app/src/main/res/drawable-xxxhdpi/ic_draw.png new file mode 100644 index 000000000..6c1924bdf Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_draw.png differ diff --git a/app/src/main/res/layout/activity_edit.xml b/app/src/main/res/layout/activity_edit.xml index b6db534a7..dcf322124 100644 --- a/app/src/main/res/layout/activity_edit.xml +++ b/app/src/main/res/layout/activity_edit.xml @@ -11,18 +11,26 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/bottom_editor_crop_rotate_actions" - android:layout_marginBottom="@dimen/activity_margin"/> + android:layout_marginBottom="@dimen/bottom_filters_height_with_margin"/> + + + + diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 72de10803..5a8762ee1 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -280,6 +280,30 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/bottom_editor_primary_actions.xml b/app/src/main/res/layout/bottom_editor_primary_actions.xml index ecbe0193b..20d8035fd 100644 --- a/app/src/main/res/layout/bottom_editor_primary_actions.xml +++ b/app/src/main/res/layout/bottom_editor_primary_actions.xml @@ -16,7 +16,6 @@ android:src="@drawable/ic_photo_filter" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/bottom_primary_crop_rotate" - app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> @@ -28,9 +27,20 @@ android:padding="@dimen/normal_margin" android:src="@drawable/ic_crop_rotate" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintEnd_toStartOf="@+id/bottom_primary_draw" app:layout_constraintStart_toEndOf="@+id/bottom_primary_filter" app:layout_constraintTop_toTopOf="parent"/> + + diff --git a/app/src/main/res/layout/dialog_slideshow.xml b/app/src/main/res/layout/dialog_slideshow.xml index 7915aa5dc..0bad63672 100644 --- a/app/src/main/res/layout/dialog_slideshow.xml +++ b/app/src/main/res/layout/dialog_slideshow.xml @@ -37,7 +37,7 @@ android:textSize="@dimen/normal_text_size"/> + + + + + + - + + + + diff --git a/app/src/main/res/menu/cab_media.xml b/app/src/main/res/menu/cab_media.xml index 26033fad3..5f3a83a8b 100644 --- a/app/src/main/res/menu/cab_media.xml +++ b/app/src/main/res/menu/cab_media.xml @@ -16,6 +16,23 @@ android:icon="@drawable/ic_share" android:title="@string/share" app:showAsAction="ifRoom"/> + + + + + + + + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 3d9aa2dc2..b489c68b0 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -31,6 +31,7 @@ Fix Date Taken value Fixing… Dates fixed successfully + Share a resized version فلتر الميديا @@ -91,7 +92,6 @@ قلب قلب أفقيا قلب عموديا - تعديل باستخدام Free Other @@ -161,7 +161,6 @@ السماح بالتحكم في سطوع الصورة باستخدام الإيماءات الرأسية السماح بالتحكم في صوت الفيديو والسطوع بالإيماءات العمودية إظهار عدد لوسائط المجلد على طريقة العرض الرئيسية - استبدال خيار المشاركة مع خيار تدوير في القائمة ملء الشاشة عرض تفاصيل موسعة على وسائط ملء الشاشة إدارة المجلدات المستبعدة السماح بتكبير الوسائط بأصبع واحد في وضع ملء الشاشة @@ -176,6 +175,7 @@ Show the Recycle Bin as the last item on the main screen Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures المصغرات @@ -197,7 +197,6 @@ يمكنك الضغط لفترة طويلة على الألبوم المطلوب وتحديد أيقونة الدبوس في الإجراء ، والتي سوف تثبيته إلى الأعلى. يمكنك تثبيت عدة مجلدات أيضًا ، وسيتم ترتيب العناصر المثبتة حسب طريقة الفرز الافتراضية. كيف يمكنني تقديم مقاطع فيديو بسرعة؟ 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. - يمكنك النقر على النصوص الحالية أو أقصى مدة قريبة من شريط السحب ، والتي ستنقل الفيديو إما للخلف أو إلى الأمام. ما الفرق بين إخفاء واستبعاد مجلد؟ يمنع الاستبعاد من عرض المجلد في الاستوديو البسيط فقط ، بينما يقوم بإخفاء بالعمل على مستوى النظام ككل ويقوم بإخفاء المجلد من المعارض الأخرى أيضًا. وهو يعمل عن طريق إنشاء ملف \".nomedia\" فارغ في المجلد المحدد ، والذي يمكنك بعد ذلك إزالته مع أي مدير ملفات أيضًا. لماذا تظهر المجلدات التي تحتوي على ملصقات أو ملصقات موسيقى تغطيها؟ @@ -206,8 +205,6 @@ يمكن أن يكون ذلك لأسباب متعددة ، ولكن حلها أمر سهل. أذهب إلى الإعدادات -> إدارة المجلدات المضمنة ، اضغط علامة الزائد وانتقل إلى المجلد المطلوب. ماذا لو كنت أرغب في رؤية بعض المجلدات الخاصة؟ لا يؤدي إضافة مجلد في \"المجلدات المضمنة\" إلى استبعاد أي شيء تلقائيًا. ما يمكنك فعله هو الذهاب إلى الإعدادات -> إدارة المجلدات المستبعدة ، واستبعاد المجلد الجذر \"/\" ، ثم إضافة المجلدات المطلوبة في الإعدادات -> إدارة المجلدات المضمنة. سيؤدي ذلك إلى إظهار المجلدات المحددة فقط ، حيث أن الاستبعاد والتضمين يكونان متكررين ، وإذا تم استبعاد أحد المجلدات وإدراجه ، فسيظهر. - الصور بملء الشاشة لها آثار غريبة ، هل يمكنني تحسين الجودة؟ - نعم ، هناك تبديل في الإعدادات يقول \"استبدل صورًا ذات زووم عميق بجودة أفضل منها\" ، يمكنك استخدام ذلك. سيؤدي ذلك إلى تحسين جودة الصور ، ولكن ستظهر بشكل واضح عند محاولة التكبير كثيرًا. هل يمكنني قص الصور باستخدام هذا التطبيق؟ نعم ، يمكنك اقتصاص الصور في المحرر ، عن طريق سحب زوايا الصورة. يمكنك الوصول إلى المحرر إما عن طريق الضغط لفترة طويلة على صورة مصغرة وتحديد تحرير ، أو تحديد تحرير من العرض بملء الشاشة. Can I somehow group media file thumbnails? diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index bf0b0aa1d..33362f9f1 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -31,6 +31,7 @@ Fix Date Taken value Fixing… Dates fixed successfully + Share a resized version Filter media @@ -87,7 +88,6 @@ Flip Flip horizontally Flip vertically - Edit with Free Other @@ -157,7 +157,6 @@ Allow controlling photo brightness with vertical gestures Allow controlling video volume and brightness with vertical gestures Show folder media count on the main view - Replace Share with Rotate at fullscreen menu Show extended details over fullscreen media Manage extended details Allow one finger zoom at fullscreen media @@ -172,6 +171,7 @@ Show the Recycle Bin as the last item on the main screen Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Thumbnails @@ -194,7 +194,6 @@ You can long press the desired album and select the Pin icon at the actionmenu, 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. - 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? @@ -204,8 +203,6 @@ 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. 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? diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 04b8538bb..d0433fd12 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -31,6 +31,7 @@ Fixar la data de presa Fixant… Data fixada correctament + Share a resized version Filtre d\'arxius @@ -87,7 +88,6 @@ Girar Horizontalment Verticalment - Editar amb Lliure Altres @@ -157,7 +157,6 @@ Permet controlar la brillantor amb gestos verticals Permet controlar el volum i la brillantor del vídeo amb gestos verticals Mostrar el número de mitjans de les carpetes a la vista principal - Reemplaçar Compartir per Girar al menú de pantalla complerta Mostrar detalls estesos sobre mitjans a pantalla complerta Gestioneu els detalls ampliats Permet fer zoom amb un sol dit a pantalla complerta @@ -172,6 +171,7 @@ Mostra la paperera de reciclatge com a últim element a la pantalla principal Permet tancar la vista de pantalla completa amb un gest avall Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Miniatures @@ -194,7 +194,6 @@ Podeu prémer l\'àlbum desitjat i seleccionar la icona de la xinxeta al menú d\'acció i el fixarà a la part superior. També podeu enganxar diverses carpetes, els elements fixats s\'ordenaran pel mètode de classificació predeterminat. Com puc fer avançar els vídeos? 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. - Podeu fer clic als textos actuals o de duració màxima que hi ha a prop de la barra de cerca, això mourà el vídeo cap a enrere o cap endavant. Quina és la diferència entre ocultar i excloure una carpeta? Excloure impedeix mostrar la carpeta només a Simple Galery, mentre que Ocultar també amaga la carpeta a altres galeries. Funciona creant un fitxer \". Nomedia \" buit a la carpeta donada, que podeu eliminar amb qualsevol gestor de fitxers. Per què apareixen les carpetes amb les portades de la música o adhesius? @@ -204,8 +203,6 @@ Què passa si vull veure només algunes carpetes concretes? L\'addició d\'una carpeta a les carpetes incloses no exclou automàticament res. El que podeu fer és anar a Configuració -> Gestionar carpetes excloses, excloure la carpeta arrel \"/\" i, a continuació, afegir les carpetes desitjades a Configuració -> Gestionar carpetes incloses. Això farà que només les carpetes seleccionades siguin visibles, ja que tant excloure com incloure són recursius i si una carpeta està exclosa i inclosa, es mostrarà. - Les imatges a pantalla completa tenen artefactes estranys, puc millorar d\'alguna manera la qualitat? - Sí, hi ha un commutador a la configuració que diu \"Substituïu imatges ampliades i de gran qualitat\", podeu fer-ho. Millora la qualitat de les imatges, però es borraran una vegada que intenteu fer zoom massa. Puc retallar imatges amb aquesta aplicació? Sí, pots retallar imatges a l\'editor, arrossegant les cantonades de la imatge. Pots accedir a l\'editor prement una miniatura d\'imatge i seleccionant Edita o seleccionant Edita des de la visualització de pantalla completa. Puc agrupar d\'alguna manera les miniatures del fitxer multimèdia? diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 473005bc5..1f08bfbd9 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -31,6 +31,7 @@ Opravit datum vytvoření Opravuji… Datumy byly úspěšně opraveny + Share a resized version Filtr médií @@ -87,7 +88,6 @@ Překlopit Překlopit vodorovně Překlopit svisle - Upravit s Volný Other @@ -157,7 +157,6 @@ Povolit ovládání jasu vertikálními tahy Povolit ovládání hlasitosti a jasu videí vertikálními tahy Zobrazit počet médií ve složce na hlavní obrazovce - Nahradit Sdílení s Otočením v celoobrazovkovém menu Zobrazit rozšířené vlastnosti přes celoobrazovkové média Spravovat rozšířené vlastnosti Povolit přibližování jedním prstem v celoobrazovkovém režimu @@ -172,6 +171,7 @@ Zobrazit odpadkový koš jako poslední položku na hlavní obrazovce Povolit zavírání celoobrazovkového režimu tažením prstu dolů Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Náhledy @@ -194,7 +194,6 @@ Můžete označit danou složku dlouhým podržením a zvolit tlačítko s obrázkem připínáčku, to jej připne na vrch. Můžete připnout i více složek, budou seřazeny podle zvoleného řazení. Jak můžu rychle posunout videa? 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. - Můžete kliknout na texty současné nebo maximální délky videa, které jsou vedle indikátoru současného progresu. To posune video buď vpřed, nebo vzad. Jaký je rozdíl mezi Skrytím a Vyloučením složky? Zatímco vyloučení předejde zobrazení složky pouze vrámci Jednoduché Galerie, skrytí ho ukryje vrámci celého systému, tedy to ovlivní i ostatní galerie. Skrytí funguje pomocí vytvoření prázdného \".nomedia\" souboru v daném adresáři, který můžete vymazat i nějakým správcem souborů. Proč se mi zobrazují složky s obaly hudebních alb, nebo nálepkami? @@ -204,8 +203,6 @@ Co v případě, že chci mít zobrazeno pouze několik složek? Přidání složky mezi Přidané složky automaticky nevyloučí ostatní. Můžete ale jít do Nastavení -> Spravovat vyloučené složky a zvolit Kořenovou složku \"/\", následně přidat požadované složky v Nastavení -> Spravovat přidané složky. To způsobí, že budou zobrazeny pouze vyžádané složky, protože vyloučení i přidání fungují rekurzivně a pokud je složka vyloučena i přidaná, bude viditelná. - Fotky přes celou obrazovku mají zhoršenou kvalitu, můžu to nějak zlepšit? - Ano, v nastavení je přepínač s textem \"Nahradit hluboko priblížiteľné obrázky s obrázky s lepší kvalitou\", můžete to zkusit. Způsobí to vyšší kvalitu obrázků, po přiblížení se ale budou rozmazávat mnohem dříve. Můžu s touto aplikací oříznout obrázky? Ano, oříznutí je možné v editoru potažením rohů obrázků. Do editoru se můžete dostat buď dlouhým podržením náhledu obrázku a zvolením menu položky Upravit nebo zvolením Upravit při celoobrazovkovém režimu. Můžu nějakým způsobem seskupit náhledy souborů? diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index f343b3e35..8f542b363 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -31,6 +31,7 @@ Fiks Dato Taget værdi Fikser… Datoer fikset med succes + Share a resized version Filtrér medier @@ -87,7 +88,6 @@ Spejlvend Spejlvend vandret Spejlvend lodret - Rediger med Fri Andet @@ -157,7 +157,6 @@ Tillad kontrol af lysstyrke på billeder med lodrette bevægelser Tillad kontrol af lyd- og lysstyrke på videoer med lodrette bevægelser Vis antal filer i hver mappe i oversigten - Erstat Del med Rotér i fuldskærmsmenuen Vis udvidede oplysninger over medier i fuldskærm Administrer udvidede oplysninger Tillad zoom med en finger når medier er i fuldskærm @@ -172,6 +171,7 @@ Vis papirkurven som sidste element på hovedskærmen Luk fuldskærmsvisning ved at swipe ned Tillad 1:1 zooming med to dobbelttryk + Always open videos on a separate screen with new horizontal gestures Miniaturer @@ -194,7 +194,6 @@ You can long press the desired album and select the Pin icon at the actionmenu, 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. - 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? @@ -204,8 +203,6 @@ 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. 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? diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index e5eea5b16..91f8e0e1d 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -31,6 +31,7 @@ Aufnahmedatum korrigieren Korrigiere… Datum erfolgreich korrigiert. + Share a resized version Filter @@ -87,7 +88,6 @@ Spiegeln Horizontal spiegeln Vertikal spiegeln - Bearbeiten mit: Beliebiges Anderes @@ -157,7 +157,6 @@ Fotohelligkeit mit vertikalen Gesten ändern Gesten für Videolautstärke/Helligkeit zulassen Medienanzahl bei Ordnern anzeigen - Teilen/Drehen im Vollbild-Menü vertauschen Dateieigenschaften in Vollbild-Anzeige einblenden Eigenschaften auswählen Ein-Finger-Zoom im Vollbild zulassen @@ -172,6 +171,7 @@ Zeige den Papierkorb als letztes Element auf dem Hauptbildschirm Erlaube das Schließen der Vollbildansicht mit einer Abwärtsgeste Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Thumbnails @@ -194,7 +194,6 @@ Du kannst lange auf das gewünschte Album drücken und im Aktionsmenü das Stecknadelsymbol auswählen; es wird nun zuoberst angepinnt. Ebenso kannst du mehrere Ordner anpinnen. Angepinnte Objekte werden nach der Standardmethode sortiert. Wie kann ich in Videos vor- oder zurückspringen? 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. - Du kannst auf den Text der aktuellen oder der maximalen Dauer nahe der Suchleiste drücken, um im Video vor- oder zurück zu springen. Was ist der Unterschied zwischen \'Verstecken\' und \'Ausschließen\' eines Ordners? \'Ausschließen\' verhindert lediglich, dass der Ordner in Schlichte Galerie angezeigt wird. \'Verstecken\' hingegen versteckt den Ordner auch vor anderen Apps. Dies funktioniert durch das Erstellen einer leeren \".nomedia\"-Datei im betroffenen Ordner, welche du mit jedem Dateimanager wieder löschen kannst. Wieso erscheinen Ordner mit Musik-Cover oder Stickers? @@ -203,8 +202,6 @@ Öffne die Galerie-Einstellungen, wähle dort \'Einbezogene Ordner verwalten\', dann das Plus-Zeichen oben rechts und navigiere zum gewünschten Ordner. Wie kann ich erreichen, dass nur ein paar definierte Ordner sichtbar sind? Einen Ordner zu den \'einbezogenen Ordnern\' hinzuzufügen, schließt nicht automatisch alle anderen aus. Eine Möglichkeit ist, in den Galerie-Einstellungen \'Ausgeschlossene Ordner verwalten\' zu wählen, den Stammordner \"/\" auszuschliessen und dann alle gewünschten Ordner in \'Einbezogene Ordner verwalten\' hinzuzufügen. - Als Vollbild angezeigte Bilder haben seltsame Artefakte. Kann ich die Qualität verbessern? - Ja, es gibt einen Schalter in den Einstellungen, gekennzeichnet mit \"Stark zoombare Bilder durch Bilder mit hoher Qualität ersetzen\". Dieser wird die Bildqualität verbessern, aber sie werden bei sehr hoher Zoomstufe unscharf. Kann ich mit dieser App Bilder zuschneiden? Ja, du kannst Bilder über das Ziehen der Bildecken im Editor zuschneiden. Du gelangst zum Editor indem du lange auf ein Vorschaubild drückst und Bearbeiten auswählst oder durch Auswählen von Bearbeiten in der Vollbildansicht. Kann ich Mediendatei-Thumbnails irgendwie gruppieren? diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 557603bd7..0a147bc9f 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -31,6 +31,7 @@ Διόρθωση ημερ. λήψης Διορθώνεται… Ημερ. διορθώθηκε με επιτυχία + Share a resized version Φιλτράρισμα πολυμέσων @@ -87,7 +88,6 @@ Αναποδογύρισμα Οριζόντιο αναποδογύρισμα Κατακόρυφο αναποδογύρισμα - Επεξεργασία με Ελεύθερο Other @@ -157,7 +157,6 @@ Να επιτρέπεται ο έλεγχος φωτεινότητας με κατακόρυφες κινήσεις Να επιτρέπεται ο έλεγχος έντασης του βίντεο και φωτεινότητας με κατακόρυφες κινήσεις (gestures) Εμφάνιση του αριθμού πολυμέσων στον φάκελο, στην κύρια οθόνη - Αντικατάσταση της "Κοινής χρήσης" με "Περιστροφή" στο μενού πλήρους οθόνης Εμφάνιση λεπτομερειών στα πολυμέσα σε κατάσταση πλήρους οθόνης Διαχείριση εκτεταμένων λεπτομερειών Να επιτρέπεται μεγένθυση με ένα δάχτυλο σε πλήρη οθόνη @@ -172,6 +171,7 @@ Εμφάνιση του Κάδου ως τελευταίο στοιχείο στην κύρια οθόνη Επιτρέψτε το κλείσιμο προβολής πλήρους οθόνης με χειρονομία προς τα κάτω Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Εικονίδια @@ -194,7 +194,6 @@ Μπορείτε να πατήσετε παρατεταμένα στο άλμπουμ και να επιλέξετε το εικονίδιο καρφιτσώματος στο μενού, αυτό θα το καρφιτσώσει στην κορυφή. Επίσης μπορείτε να καρφιτσώσετε πολλαπλούς φακέλους, τα καρφιτσωμένα αντικείμενα θα είναι ταξινομημένα με την προεπιλεγμένη μέθοδο. Πώς μπορώ να τρέξω μπροστά (fast-forward) τα βίντεο; 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. - Μπορείτε να αγγίξετε στο τρέχον ή στο κείμενο μέγιστης διάρκειας κοντά στην μπάρα αναζήτησης. Αυτό θα μετακινήσει το βίντεο μπροστά ή πίσω. Ποια είναι διαφορά μεταξύ απόκρυψης και εξαίρεσης ενός φακέλου; Η εξαίρεση δεν επιτρέπει την εμφάνιση του φακέλου μόνο στο Simple Gallery, ενώ η απόκρυψη λειτουργεί σε επίπεδο συστήματος και θα αποκρύψει τον φάκελο και από άλλες εφαρμογές γκάλερι. Λειτουργεί δημιουργώντας ένα άδειο \".nomedia\" αρχείο στον επιλεγμένο φάκελο, το οποίο μπορείτε να το διαγράψετε και με οποιονδήποτε διαχειριστή αρχείων. Γιατί εμφανίζονται φάκελοι με εξώφυλλο μουσικής ή αυτόκολλητα; @@ -204,8 +203,6 @@ Πώς μπορώ να επιλέξω μόνο κάποιους φακέλους να εμφανίζονται; Η προσθήκη ενός φακέλου στους Συμπεριλαμβανόμενους Φακέλους δεν εξαιρεί αυτόματα τίποτα. Μπορείτε να πάτε στις Ρυμίσεις-> Διαχείριση Εξαιρεμένων Φακέλων, εξαιρέστε τον ριζικό φάκελο \"/\", έπειτα προσθέστε τους φακέλους στο Ρυθμίσεις -> Διαχείριση Συμπεριλαμβανομένων Φακέλων. Αυτό θα κάνει ορατούς μόνο τους επιλεγμένους φακέλους, καθώς η εξαίρεση και η συμπερίληψη λειτουργούν αναδρομικά και αν ενας φάκελος ανήκει και στα δύο, θα εμφανιστεί. - Οι εικόνες πλήρους οθόνης έχουν κάποια περίεργα σημάδια. Μπορώ κάπως να βελτιώσω την ποιότητα; - Ναι. Υπάρχει ένας διακόπτης στις Ρυθμίσεις με το κείμενο \"Αντικατάσταση των φωτογραφιών που απαιτούν ζούμ με άλλες καλύτερης ποιότητας\". Μπορείτε να χρησιμοποιήσετε αυτό. Θα βελτιώσει την ποιότητα των φωτογραφιών, αλλά θα θολώσουν στο μεγάλο ζουμ. Μπορώ να περικόψω εικόνες με την εφαρμογή; Ναι, μπορείτε να περικόψετε εικόνες στον επεξεργαστή, σύροντας τις γωνίες εικόνας. Μπορείτε να μεταβείτε στον επεξεργαστή είτε πατώντας παρατεταμένα μια μικρογραφία εικόνας και επιλέγοντας Επεξεργασία, είτε επιλέγοντας Επεξεργασία από την προβολή πλήρους οθόνης. Μπορώ να ομαδοποιήσω κάπως τις μικρογραφίες των αρχείων πολυμέσων? diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index a4ff72ed6..89f0bd44e 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -31,6 +31,7 @@ Fijar fecha de toma Fijando… Fecha fijada correctamente + Share a resized version Filtro de medios @@ -87,7 +88,6 @@ Girar Horizontalmente Verticalmente - Editar con Libre Otros @@ -157,7 +157,6 @@ Permite controlar el brillo con gestos verticales Permite controlar el volumen y el brillo del video con gestos verticales Mostrar el conteo de medios de las carpetas en la vista principal - Reemplazar Compartir con Girar en el menú de pantalla completa Mostrar detalles extendidos sobre medios en pantalla completa Administrar detalles ampliados Permitir zoom con un dedo en pantalla completa @@ -172,6 +171,7 @@ Mostrar la Papelera de reciclaje como el último elemento en la pantalla principal Permite cerrar la vista de pantalla completa con un gesto hacia abajo. Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Miniaturas @@ -194,7 +194,6 @@ Puede aguantar pulsado el álbum deseado y seleccionar el ícono Pin en el menú de acción, que lo fijará en la parte superior. También puede anclar varias carpetas, los artículos fijados se ordenarán por el método de clasificación predeterminado. ¿Cómo puedo avanzar 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. - Puede hacer clic en los textos de duración actual o máxima cerca de la barra de búsqueda, que moverán el video hacia atrás o hacia adelante. ¿Cuál es la diferencia entre ocultar y excluir una carpeta? Excluir evita mostrar la carpeta solo en Simple Gallery, mientras que Ocultar funciona en el sistema y oculta la carpeta de otras galerías también. Funciona al crear un archivo \".nomedia \" vacío en la carpeta determinada, que luego puede eliminar también con cualquier administrador de archivos. ¿Por qué aparecen las carpetas con la portada de la música o las pegatinas? @@ -204,8 +203,6 @@ ¿Qué pasa si quiero solo algunas carpetas concretas visibles? Agregar una carpeta en las carpetas incluidas no excluye automáticamente nada. Lo que puede hacer es ir a Ajustes -> Administrar carpetas excluidas, excluir la carpeta raíz \"/\", luego agregar las carpetas deseadas en Configuración -> Administrar carpetas incluidas. Esto hará que solo las carpetas seleccionadas sean visibles, ya que tanto la exclusión como la inclusión son recursivas y si una carpeta está excluida e incluida, aparecerá. - Las imágenes a pantalla completa tienen artefactos extraños, ¿puedo de alguna manera mejorar la calidad? - Sí, hay una alternancia en Ajustes que dice \"Reemplazar imágenes con zoom profundo con las de mejor calidad\", puede usar eso. Mejorará la calidad de las imágenes, pero se volverán borrosas una vez que intente ampliar demasiado. ¿Puedo recortar imágenes con esta aplicación? Sí, puede recortar imágenes en el editor arrastrando las esquinas de la imagen. Puede acceder al editor pulsando prolongadamente una imagen en miniatura y seleccionando Editar, o seleccionando Editar en la vista de pantalla completa. ¿Puedo de alguna manera agrupar miniaturas de archivos multimedia? diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 012074dbb..d4410137c 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -31,6 +31,7 @@ Fix Date Taken value Fixing… Dates fixed successfully + Share a resized version Suodata media @@ -87,7 +88,6 @@ Pyöräytä Pyöräytä vaakasuoraan Pyöräytä pystysuoraan - Muokkaa sovelluksella Free Other @@ -157,7 +157,6 @@ Salli kirkkauden säätäminen pystysuorilla eleillä Salli videon äänenvoimakkuuden ja kirkkauden säätö pystysuorilla eleillä Näytä kansioiden sisällön määrä päänäkymässä - Korvaa jakaminen kääntämisellä koko näytön tilassa Näytä yksityiskohtaiset tiedot täyden näytön tilassa Hallitse yksityiskohtaisia tietoja Salli lähentäminen yhdellä sormella täyden ruudun tilassa @@ -172,6 +171,7 @@ Show the Recycle Bin as the last item on the main screen Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Esikatselukuvat @@ -194,7 +194,6 @@ You can long press the desired album and select the Pin icon at the actionmenu, 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. - 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? @@ -204,8 +203,6 @@ 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. 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? diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 7a9554894..013a04193 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -31,6 +31,7 @@ Corriger la valeur des dates de prise des photos Correction en cours.... Dates corrigées + Share a resized version Filtrer les médias @@ -87,7 +88,6 @@ Retourner Retourner horizontalement Retourner verticalement - Modifier avec Libre Other @@ -157,7 +157,6 @@ Contrôler la luminosité de la photo avec des gestes verticaux Contrôler le volume et la luminosité de la vidéo avec des gestes verticaux Afficher le nombre de fichiers dans les dossiers - Remplacer \"Partager\" par \"Pivoter\" en plein écran Afficher en surimpression les informations supplémentaires du média en plein écran Gérer les informations supplémentaires Effectuer le zoom avec un doigt sur une image en plein écran @@ -172,6 +171,7 @@ Afficher la corbeille en dernière place sur l\'écran principal Fermeture de la vue plein écran par un geste vers le bas Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Miniatures @@ -193,7 +193,6 @@ Vous devez simplement à effectuer un appui prolongé sur l\'album en question et choisir l\'icône \"Épingler\" dans le menu d\'actions. Vous pouvez en épingler plusieurs. Les éléments épinglés seront alors triés selon l\'ordre par défaut. Comment avancer rapidement dans les vidéos ? 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. - Vous pouvez appuyer sur la durée actuelle ou totale de la vidéo sur la barre de progression, la vidéo reculera ou avancera selon votre choix. Quelle est la différence entre masquer et exclure un dossier ? \"Exclure un dossier\" permet de ne pas l\'afficher uniquement dans Simple Gallery, alors que \"Masquer un dossier\" rend le dossier invisible sur l\'ensemble de l\'appareil, y compris les autres applications de galerie. Dans le dernier cas, un fichier \".nomedia\" est créé dans le dossier masqué, et peut être supprimé avec n\'importe quel explorateur de fichiers. Pourquoi des dossiers avec des pochettes d\'albums musicaux ou des miniatures d\'images sont affichés ? @@ -202,8 +201,6 @@ Cela peut arriver pour de multiples raisons, mais c\'est facile à résoudre. Allez dans \"Paramètres\", puis \"Gérer les dossiers inclus\", appuyez sur \"+\" et sélectionnez le dossier voulu. Comment faire apparaître uniquement certains dossiers ? Ajouter un dossier dans les \"Dossiers inclus\" rend visible l\'ensemble du contenu du dossier. Pour exclure certains dossiers, il faut aller dans \"Paramètres\", puis \"Gérer les dossiers exclus\", exclure le dossier racine \"/\", puis ajouter les dossiers souhaités dans \"Paramètres\", puis \"Gérer les dossiers inclus\". Seuls les dossiers sélectionnés seront visibles, du fait que les exclusions et inclusions sont récursives, et si un dossier est à la fois exclus et inclus, il sera affiché. - Les images en plein écran contiennent des artefacts, est-ce possible d\'améliorer la qualité ? - Oui, il existe dans \"Paramètres\" une option \"Afficher les images avec la plus haute qualité possible\", mais les images seront alors floues si vous zoomez trop. Puis-je recadrer des images avec cette application ? Oui, vous pouvez recadrer les images dans l\'éditeur en faisant glisser les coins de l\'image. Vous pouvez accéder à l\'éditeur en appuyant longuement sur une vignette d\'image et en sélectionnant \"Modifier\", ou en sélectionnant \"Modifier\" en mode plein écran. Puis-je regrouper les miniatures des fichiers multimédias ? diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index df63a45aa..1bfcab564 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -31,6 +31,7 @@ Fix Date Taken value Fixing… Dates fixed successfully + Share a resized version Filtrar medios @@ -87,7 +88,6 @@ Voltear Voltear horizontalmente Voltear verticalmente - Editar con Free Other @@ -157,7 +157,6 @@ Permitir controlar o brillo da foto con xestos verticais Permitir controlar o volume do vídeo e o brillo con xestos verticáis Mostrar a conta de medios do cartafol na vista principal - Substituír Compartir con Rotar no menú de pantalla completa Mostrar información pormenorizada sobre medios a pantalla completa Xestionar información polo miúdo Permitir zoom con un dedo a pantalla completa @@ -172,6 +171,7 @@ Show the Recycle Bin as the last item on the main screen Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Iconas @@ -194,7 +194,6 @@ Pode manter premido o álbume e escoller a icona de Fixar no menú de accións, esto fixarao arriba. Pode fixar varios cartafoles tambén, os elementos fixados estarán ordenados polo criterio por omisión. Cómo podo aumentar a velocidade de reprodución de vídeo? 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. - Pode pulsar no texto de duración actual ou máxima preto da barra de busca, esto moverá ou vídeo hacia adiante ou atrás. Cal é a diferenza entre agochar e excluír un cartafol? A Exclusión prevén que se mostre o cartafol só en Simple Gallery, mentras Agochar funciona para todo o sistema e agocha o cartafol para outras galerías tamén. Esto funciona creando un ficheiro baldeiro de nome \".nomedia\" no cartafol, que tamén pode quitar con calquer xestor de ficheiros. Por qué aparecen cartafoles de música con portadas ou pegatinas? @@ -204,8 +203,6 @@ E qué pasa si só quero que sexan visibles certos cartafoles Engadir un cartafol a Cartafoles incluídos non exclúe nada de xeito automático. O que pode facer é ir a Axustes -> Xestionar cartafoles incluídos, excluír o cartafol root \"/\", e despóis engadir os cartafoles desexados con Axustes -> Xestionar Cartafoles Incluídos. Esto fará visibles só aos cartafoles escollidos, como tanto excluír e incluír son recursivos e si está excluído e logo incluído, será mostrado. - As imaxes a pantalla completa teñen píxeles extranos, podo mellorar a calidade da imaxe? - Si, hai unha opción en Axustes que di \"Substituír imaxes con un gran zoom con imaxes de mellor calidade\", pode usar eso. mellorará a calidade das imaxes, mais farase máis borrosaxa si intenta facer moito zoom. 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? diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 205680116..87786044b 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -31,6 +31,7 @@ Ispravi vrijednost datuma snimanja Popravljam… Datumi uspješno popravljeni + Share a resized version Filtriranje medija @@ -87,7 +88,6 @@ Okreni Okreni horizontalno Okreni vertikalno - Uredi pomoću Slobodan odabir Ostalo @@ -157,7 +157,6 @@ Omogućite kontrolu svjetline fotografije vertikalnim pokretima Omogući kontrolu glasnoće videa i svjetline pomoću vertikalnih pokreta Prikaz broja medija mapa u glavnom prikazu - Zamjeni Dijeli s Rotiraj pri pregledu datoteka Prikaži proširene pojedinosti preko medija na cijelom zaslonu Upravljaj proširenim pojedinostima Omogući zumiranje jednim prstom na mediju cijelog zaslona @@ -172,6 +171,7 @@ Prikaži koš za smeće kao posljednju stavku na glavnom zaslonu Omogućite zatvaranje prikaza preko cijelog zaslona pokretom prema dolje Dopusti zumiranje 1: 1 s dva dvostruka dodira + Always open videos on a separate screen with new horizontal gestures Sličice @@ -194,7 +194,6 @@ Dugo pritisnute željeni album i odaberite ikonu igle na akcijskom izborniku, koji će ga pričvrstiti na vrh. Možete prikvačiti više mapa odjednom, prikvačene stavke će biti razvrstane prema zadanom načinu razvrstavanja. Kako mogu ubrzati 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. - Možete pritisnuti trenutačno vrijeme ili ukupno trajanje videozapisa na traci napretka, videozapis će se prema Vašem izboru pomicati unatrag ili prema naprijed. Koja je razlika između skrivanja i izuzimanja mape? Izuzimanje sprječava prikaz mape samo u Jednostavnoj galeriji, a skrivanje radi na razini sustava i skriva mapu iz drugih galerija. Djeluje stvaranjem praznih \".nomedia\" datoteka u zadanoj mapi, koju možete ukloniti pomoću bilo kojeg upraviteljem datoteka. Zašto se prikazuju mape s naslovnicama albuma i minijaturama slika? @@ -204,8 +203,6 @@ Što ako želim vidjeti samo nekoliko određenih mapa? Dodavanje direktorija u uključene mape ne izuzima ništa automatski. Da biste to učinili, idite na "Postavke", a zatim "Upravljanje izuzetim mapama", izuzmite korijenski direktorij \"/\", a zatim dodajte željene direktorije u "Postavke" i "Upravljanje uključenim mapama". Samo će odabrane mape biti vidljive, jer su izuzimanja i uključivanja rekurzivni, a ako je mapa isključena i uključena, bit će prikazana. - Slike na cijelom zaslonu imaju čudne artefakte, mogu li nekako poboljšati kvalitetu? - Da, u "Postavkama" postoji opcija "Zamjena duboko zumiranih slika s kvalitetnijim slikama", ali slike će biti zamućene ako zumirate previše. Mogu li izrezati slike pomoću ove aplikacije? Da, možete obrezati slike u uređivaču povlačenjem uglova. Možete doći do uređivača dugim pritiskom na minijaturu slike i odabirom Uređivanje ili odabirom Uredi iz prikaza preko cijelog zaslona. Mogu li nekako grupirati sličice medijskih datoteka? diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 3d5fe9350..2db88f5cf 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -31,6 +31,7 @@ Dátum javítása Javítás… Sikeres dátum javítás + Share a resized version Média szűrő @@ -87,7 +88,6 @@ Tükrözés Tükrözés vízszintesen Tükrözés függőlegesen - Szerkesztés ezzel Kötetlen Egyéb @@ -158,7 +158,6 @@ Engedélyezi a kép fényerő módosítást függőleges gesztusokkal Engedélyezi a videó hangerő és fényerő módosítást függőleges gesztusokkal Mutassa a fájlok számát a mappákban - Cserélje meg a Megosztást a Forgatással a teljes képernyős menüben Mutassa a kiterjesztett adatokat a teljes képernyős médián keresztül Bővített részletek kezelése Engedélyezi az egy ujjas nagyítást a teljes képernyős médiában @@ -173,6 +172,7 @@ Mutassa a Lomtárat a fő képernyő utolsó elemeként Engedélyezi a teljes képernyős nézetet a lefelé mozdulattal Engedélyezi az 1:1 nagyítást két dupla érintéssel + Always open videos on a separate screen with new horizontal gestures Miniatűrök @@ -195,7 +195,6 @@ A következő alkalommal, amikor megpróbál megnyitni egy képet vagy videót, Hosszan nyomja meg a kívánt albumot, és válassza ki a Kitűzés ikont a művelet menüben, ami rögzíti felülre. Többféle mappát is kitűzhet, ezeket az elemeket az alapértelmezett rendezési mód szerint rendezi. Hogyan tudom előre tekerni a videókat? Húzhatja az ujját vízszintesen a videolejátszón, vagy kattintson az aktuális vagy a max. időtartam szövegekre a keresősáv közelében. Ez visszafelé vagy előre mozgatja a videót. - Húzhatja az ujját vízszintesen a videolejátszón, vagy kattintson az aktuális vagy a max. időtartam szövegekre a keresősáv közelében. Ez visszafelé vagy előre mozgatja a videót. Mi a különbség a mappa elrejtése és kizárása között? A Kizárás megakadályozza, hogy a mappát a Simple Gallery megjelenítse, az Elrejtés pedig rendszer szinten működik, és elrejti a mappát más galériákból is. Úgy működik, hogy létrehoz egy üres \". nomedia\" nevű fájlt az adott mappában, amelyet bármikor eltávolíthat bármilyen fájlkezelővel is. Miért jelennek meg a zenei borítóval vagy matricával rendelkező mappák? @@ -205,8 +204,6 @@ A következő alkalommal, amikor megpróbál megnyitni egy képet vagy videót, Mi van, ha csak néhány különleges mappát szeretnék látni? A Befoglalt mappákhoz tartozó mappák hozzáadása nem zár ki automatikusan semmit. Amit tehetünk, menjünk a Beállítások -> Kizárt mappák kezelése, kizárjuk a gyökérmappát \"/ \", utána hozzáadjuk a kívánt mappákat a Beállítások -> Befoglalt mappák kezelése menüpontban. Ezzel csak a kiválasztott mappák láthatók, mivel a kizárás és a befoglalás rekurzív. Ha egy mappát hozzáadunk mindkettőhöz, akkor megjelenik. - A teljes képernyős képek furcsán néznek ki, tudnám valahogy javítani a minőséget? - Igen, van egy kapcsoló a Beállításokban: \"Cserélje le a mély nagyítású képeket jobb minőségűekre\", akkor használhatja. Javítja a képek minőségét, de elmosódik, ha túl nagy zoomolást használ. Tudom vágni a képeket ezzel az alkalmazással? Igen, megvághatja a képeket a szerkesztőben a kép sarkainak húzásával. A szerkesztőhöz eljuthat egy miniatűr kép hosszú megnyomásával és a Szerkesztés választásával, vagy a Szerkesztés választásával a teljes képernyős nézetben. Valamilyen módon össze tudom csoportosítani a médiafájl bélyegképeit? diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 2b4c0c882..7129f35b8 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -31,6 +31,7 @@ Perbaiki Tanggal Diambil Memperbaiki… Tanggal berhasil diperbaiki + Share a resized version Filter media @@ -87,7 +88,6 @@ Balik Balik horizontal Balik vertikal - Edit dengan Bebas Lainnya @@ -157,7 +157,6 @@ Izinkan mengontrol kecerahan foto dengan gerakan vertikal Izinkan mengontrol kecerahan dan volume video dengan gerakan vertikal Tampilkan jumlah folder media di tampilan utama - Ganti tombol Bagikan dengan Rotasi di menu layar penuh Tampilkan detail tambahan saat layar penuh Atur detail tambahan Izinkan zoom satu jari di layar penuh @@ -172,6 +171,7 @@ 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 Thumbnail @@ -194,7 +194,6 @@ 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. - Anda bisa mengklik teks durasi saat ini/maksimal di dekat penggeser durasi, itu akan memajukan atau memundurkan video. 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. Mengapa folder dengan gambar album musik atau stiker muncul? @@ -204,8 +203,6 @@ 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. Itu akan membuat folder yang dipilih saja yang muncul, dan jika sebuah folder disertakan dan dikecualikan secara bersamaan, folder tersebut akan muncul. - Gambar layar penuh terlihat pecah, bisakah ditingkatkan kualitasnya? - Ya, ada opsi di Setelan \"Ganti zoom mendalam dengan kualitas gambar yang lebih bagus\", Anda bisa menggunakannya. Ini akan meningkatkan kualitas gambar, namun gambar akan terlihat kabur jika Anda zoom terlalu banyak. 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? diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 080359793..f5939868a 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -31,6 +31,7 @@ Correggi valore Data acquisizione Correzione in corso… Date aggiornate correttamente + Share a resized version Filtra i file @@ -87,7 +88,6 @@ Capovolgi Capovolgi orizzontalmente Capovolgi verticalmente - Modifica con Libero Altro @@ -157,7 +157,6 @@ Controlla la luminosità delle foto con gesti verticali Gestisci il volume e la luminosità dei video con gesti verticali Mostra numero elementi nella cartella - Sostituisci Condividi con Ruota a schermo intero Mostra informazioni estese su media a schermo intero Gestisci le informazioni estese Abilita zoom con un dito su media a schermo intero @@ -172,6 +171,7 @@ Mostra il cestino come ultimo elemento nella schermata principale Chiudi la visuale a schermo intero con un gesto verso il basso Permetti l\'ingrandimento 1:1 con un doppio tasto + Apri sempre i video su uno schermo separato con i nuovi movimenti orizzontali Anteprime @@ -194,7 +194,6 @@ Si può toccare a lungo l\'album desiderato e selezionare l\'icona puntina nel menù azioni, ciò lo fisserà in cima. Si possono anche fissare varie cartelle, gli elementi fissati saranno ordinati dal metodo di ordinamento predefinito. Come avanzo velocemente nei video? Si possono trascinare le proprie dita orrizontalmente sul video, oppure cliccando i testi accanto alla barra di avanzamento. In questo modo il video andrà avanti o indietro. - Si può cliccare sui testi di durata attuale o massima vicino alla barra di avanzamento, ciò avanzerà o riavvolgerà il video. Che differenza c\'è tra nascondere ed escludere una cartella? Escludere impedisce la visualizzazione della cartella solo in Semplice Galleria, mentre nascondere ha effetto in tutto il sistema e nasconde la cartella anche alle altre gallerie. Funziona creando un file vuoto \".nomedia\" nella cartella in questione, si possono anche rimuovere successivamente con qualsiasi gestore dei file. Perchè vengono mostrate cartelle con copertine o adesivi di musica? @@ -204,8 +203,6 @@ Che fare se voglio rendere visibili solo poche particolari cartelle? Aggiungere una cartella nelle Cartelle Incluse non esclude automaticamente nulla. Quello che puoi fare è andare in Impostazioni → Gestisci le cartelle escluse, escludi la cartella root \"/\", poi aggiungi le cartelle desiderate in Impostazioni → Gestisci le cartelle incluse. Ciò renderà visibili solo le cartelle selezionate, dato che sia l\'esclusione che l\'inclusione sono ricorsive e se una cartella è sia esclusa che inclusa, verrà mostrata. - Le immagini a schermo intero hanno strani artefatti, posso migliorarne la qualità in qualche modo? - Sì, c\'è un\'opzione nelle impostazioni che dice \"Sostituisci le immagini ingrandibili a fondo con altre di migliore qualità\". Ciò migliorerà la qualità delle immagini, ma saranno sfuocate quando si proverà a ingrandirle troppo. Posso ritagliare le immagini con questa app? Sì, si possono ritagliare le immagini nell\'editor, trascinando gli angoli dell\'immagine. Si può accedere all\'editor sia premendo a lungo la miniatura di un\'immagine e selezionando Modifica, oppure selezionando Modifica mentre si vede una foto a schermo intero. Posso raggruppare in qualche modo le miniature dei file? diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 82a57ac7d..9d8334625 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -31,6 +31,7 @@ 撮影日の値を修正 修正中… 撮影日が正常に修正されました + Share a resized version 表示する形式 @@ -87,7 +88,6 @@ 反転 水平方向に反転 垂直方向に反転 - 他のアプリで編集 Free Other @@ -157,7 +157,6 @@ 垂直の動作で写真の明るさを制御 音量と明るさを縦の動作で変更 フォルダ内のメディア数を表示する - フルスクリーン時の「共有」を「回転」に置き換える フルスクリーンに詳細を重ねて表示する 詳細表示を管理する メディアを指だけでズームする @@ -172,6 +171,7 @@ ごみ箱をメイン画面の最後に表示 Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures サムネイル設定 @@ -194,7 +194,6 @@ You can long press the desired album and select the Pin icon at the actionmenu, that will pin it to the top. You can pin multiple folders too, pinned items will be sorted by the default sorting method. 動画を早送りするにはどうすればよいですか? 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? @@ -204,8 +203,6 @@ 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. 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? diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 143ab2f23..b13747387 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -31,6 +31,7 @@ Fix Date Taken value Fixing… Dates fixed successfully + Share a resized version 미디어 필터 설정 @@ -87,7 +88,6 @@ 반전 가로 반전 세로 반전 - 이미지편집 프로그램 연결 Free Other @@ -157,7 +157,6 @@ 상하 제스처로 사진 밝기 제어 수직 제스처로 비디오 볼륨 및 밝기 제어 폴더에 포함된 미디어파일 수 표시 - 전체화면 메뉴의 공유 아이콘을 회전 아이콘으로 변경 전체화면 모드에서 세부정보 표시 확장된 세부정보 관리 전체화면 모드에서 한 손가락으로 확대 및 축소 @@ -172,6 +171,7 @@ Show the Recycle Bin as the last item on the main screen Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures 섬네일 @@ -194,7 +194,6 @@ You can long press the desired album and select the Pin icon at the actionmenu, 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. - 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? @@ -204,8 +203,6 @@ 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. 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? diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 0e5945bae..00f8dfb82 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -31,6 +31,7 @@ Fix Date Taken value Fixing… Dates fixed successfully + Share a resized version Filtruoti mediją @@ -87,7 +88,6 @@ Apversti Apversti horizontaliai Apversti vertikaliai - Redaguoti su Free Other @@ -157,7 +157,6 @@ Leisti valdyti nuotraukų ryškumą vertikaliais gestais Leisti kontroliuoti vaizdo įrašo garsumą ir ryškumą vertikaliais gestais Rodyti aplanko bylų skaičių pagrindiniame rodinyje - Pakeisti bendrinti su rotacija viso ekrano meniu Rodyti išsamią informaciją per visą ekraną Tvarkykite išsamią informaciją Leisti vienu pirštu pritraukti viso ekrano rėžime @@ -172,6 +171,7 @@ Show the Recycle Bin as the last item on the main screen Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Miniatiūros @@ -194,7 +194,6 @@ Galite ilgai paspausti norimą albumą ir pasirinkti "Prisegti" piktogramą, esančią meniu "Veiksmo meniu", viršuje. Galite prisegti kelis aplankus, prisegti elementai bus rūšiuojami pagal numatytąjį rūšiavimo metodą. Kaip galėčiau greitai prasukti vaizdo įrašus? 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. - Galite spustelėti tekstus šalia slinkties juostos, kad būtų perkeltas vaizdo įrašas atgal arba į priekį. Koks skirtumas tarp slėpimo ir išskyrimo iš aplanko? Išskyrimas neleidžia rodyti aplanko tik paprastoje galerijoje, tuo tarpu slėpimas slepia aplanką iš kitų galerijų. Tai veikia, sukuriant tuščią \ ". Nomedia \" bylą tam tikrame aplanke, kurį vėliau galite pašalinti bet kuria bylų tvarkykle. Kodėl pasirodo aplankai su muzikos viršeliu ar lipdukais? @@ -204,8 +203,6 @@ Ką daryti, jei noriu matyti tik keletą konkrečių aplankų? Pridėjus aplanką į "Įtraukti aplankai", automatiškai neįtraukiama nieko. Ką jūs galite padaryti, eikite į Nustatymai -> Tvarkyti išskirtus aplankus, išskirkite šakninį aplanką \ "/ \", tada pridėkite norimus aplankus, esančius Nustatymai -> Tvarkyti įtrauktas aplankas. Tai leis matyti tik tuos pasirinktus aplankus, nes abu atmetami ir įtraukti yra rekursyvūs, ir jei aplankas yra išskirtas ir įtrauktas, jis bus rodomas. - Viso ekrano atvaizdai turi keistus artefaktus, galiu kokiu nors būdu pagerinti kokybę? - Taip, "Nustatymuose" perjunkite \ "Pakeisti giliuosius, patobulintus vaizdus geresnės kokybės vaizdais \", galite tai naudoti. Tai pagerins vaizdų kokybę, tačiau kai jūs pabandysite per daug padidinti vaizdą, jie bus neryškūs. Ar galiu apkarpyti vaizdus naudojant šią programėlę? Taip, redaguodami vaizdus, galite juos apkarpyti, vilkdami vaizdo kampus. Galite patekti į redaktorių ilgai paspaudę vaizdo miniatiūrą ir pasirinkę "Redaguoti" arba iš viso ekrano rodinio pasirinkę "Redaguoti". Can I somehow group media file thumbnails? diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index ba6a24e90..153802ae6 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -31,6 +31,7 @@ Korriger Dato tatt-verdi Korrigerer… Datoer er korrigerte + Share a resized version Filtrer media @@ -87,7 +88,6 @@ Speilvend Speilvend horisontalt Speilvend vertikalt - Rediger med Fri Annen @@ -122,7 +122,7 @@ Endre visningstype Rutenett Liste - Group direct subfolders + Grupper direkte undermapper Grupper etter @@ -157,7 +157,6 @@ Tillat å styre fotolysstyrke med vertikale bevegelser Tillat å styre videovolum og lysstyrke med vertikale bevegelser Vis mediaantallet i mapper på hovedvisningen - Erstatt Del med Roter i meny ved mediavisning Vis flere detaljer i mediavisningen Velg detaljer Tillat en-finger-zoom i mediavisningen @@ -172,6 +171,7 @@ Vis papirkurven som siste element på hovedskjermen Tillat lukking av mediavisningen med en nedoverbevegelse Tillat å zoome 1:1 med to dobbeltrykk + Åpne alltid videoer på en separat skjerm med nye horisontale bevegelser Minibilder @@ -194,7 +194,6 @@ You can long press the desired album and select the Pin icon at the actionmenu, 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. - 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? @@ -204,8 +203,6 @@ 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. 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? diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 6aa91343e..77996d5ea 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -31,6 +31,7 @@ Datum opname corrigeren Corrigeren… Datums zijn gecorrigeerd + Verkleinde versie delen Media filteren @@ -87,7 +88,6 @@ Kantelen Horizontaal kantelen Verticaal kantelen - Bewerken met Vrij Anders @@ -157,7 +157,6 @@ Helderheid voor afbeeldingen aanpassen met verticale veeggebaren Volume en helderheid voor video\'s aanpassen met verticale veeggebaren Aantallen in mappen tonen - Menu-item Draaien vastzetten in volledig scherm (in plaats van Delen) Uitgebreide informatie tonen in volledig scherm Uitgebreide informatie Met één vinger zoomen in volledig scherm @@ -172,6 +171,7 @@ Prullenbak als laatste item tonen Naar beneden vegen om volledig scherm af te sluiten 1:1 zoomen na 2x dubbelklikken + Video\'s altijd in apart scherm met horizontale veeggebaren openen Miniatuurvoorbeelden @@ -185,37 +185,34 @@ Bestand tonen/verbergen - How can I make Simple Gallery the default device gallery? - 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 actionmenu, 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. - 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, 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. - 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. - 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. + Hoe kan ik Eenvoudige Galerij instellen als standaard-app voor foto\'s en video\'s? + Zoek eerst de huidige standaard-app voor foto\'s en video\'s in de Android-instellingen (via \"Apps\" of "\Apps en meldingen\"). Klik bij de App-info op \"Standaardwaarden wissen\" (soms onder \"Standaard openen\"). + Bij het openen van een foto of video zal de volgende keer een keuzescherm verschijnen, waarin Eenvoudige Galerij als standaard-app kan worden ingesteld. + Ik heb de app beveiligd met een wachtwoord, maar ben het wachtwoord nu vergeten. Wat kan ik doen? + Deïnstalleer en herinstalleer de app, of ga naar de app in de Android-instellingen (via \"Apps (en meldingen)\" -> \"App-info\") en kies via \"Opslagruimte\" voor \"Gegevens wissen\". Hiermee worden alleen de instellingen van deze app gewist. + Hoe kan ik een map bovenaan vastzetten? + Druk lang op het map en kies vervolgens de punaise in het actiemenu. Als er meerdere mappen zijn vastgezet, zullen deze worden weergeven op basis van de standaardsortering. + Hoe kan ik terug- of vooruitspoelen in video\'s? + Sleep horizontaal over de videospeler, of klik bij de zoekbalk op de cijfers die de huidige voortgang of de lengte weergeven. Hierbij zal de video respectievelijk terug- of vooruitspringen. + Wat is het verschil tussen het verbergen en het uitsluiten van mappen? + Met \"Uitsluiten\" wordt het tonen van de map alleen binnen deze app voorkomen, terwijl \"Verbergen\" de map ook zal verbergen voor andere galerij-apps. Met \"Verbergen\" wordt een bestand genaamd \".nomedia\" in de te verbergen map aangemaakt (het verwijderen van dit bestand uit de map maakt het verbergen ongedaan). + Waarom zie ik mappen met stickers of covers van muziekalbums? + Soms worden er wat ongebruikelijke afbeeldingen van andere apps getoond. Deze zijn gemakkelijk uit het overzicht te halen door lang te drukken op de map en vervolgens te kiezen voor \"Uitsluiten\". In het daaropvolgende venster is ook de bovenliggende map te kiezen; dit zou het tonen van soortgelijke ongewenste items kunnen voorkomen. + Een bepaalde map met afbeeldingen wordt niet getoond. Wat kan ik doen? + Dit kan verschillende redenen hebben, maar is eenvoudig op te lossen. Ga naar \"Instellingen\" -> \"Toegevoegde mappen beheren\", klik vervolgens op het plus-symbool en navigeer naar de gewenste map. + Wat als ik slechts een beperkt aantal mappen wil laten zien? + Het toevoegen van mappen aan de lijst bij \"Toegevoegde mappen beheren\" sluit niet automatisch alle andere mappen uit. Sluit daarom de hoofdmap \"/\" uit via \"Instellingen\" -> \"Uitgesloten mappen beheren\" en voeg vervolgens de te tonen mappen toe bij \"Instellingen\" -> \"Toegevoegde mappen beheren\". + Dit zal ervoor zorgen dat alleen de toegevoegde mappen worden getoond (mappen toevoegen of uitsluiten gebeurt recursief, maar een toegevoegde map zal altijd worden getoond). + Kan ik afbeeldingen bijsnijden met deze app? + Ja, dat kan bij \"Bewerken\" door de hoeken te verslepen. Druk lang op een afbeelding in het overzicht of ga naar het volledig scherm en klik vervolgens op \"Bewerken\". + Hoe kan ik mediabestanden groeperen? + Kies het menu-item \"Groeperen op\" om op basis van verschillende criteria te groeperen. Dit kan ook ongeacht de mappenstructuur als voor de functie \"Alles weergeven\" is gekozen. + Sorteren op Datum opname lijkt niet te werken. Hoe kan ik dit oplossen? + Waarschijnlijk zijn de bestanden gekopieerd vanaf een andere locatie. Selecteer de bestanden en kies \"Datum opname corrigeren\". + Ik zie \"color banding\" op de afbeeldingen. Hoe kan ik de kwaliteit verbeteren? + In de meeste gevallen werkt de huidige methode voor het weergeven van afbeeldingen prima, maar met de instelling \"Afbeeldingen in de hoogst mogelijke kwaliteit weergeven\" onder \"Afbeeldingen ver inzoomen\" kan een nog betere kwaliteit worden bewerkstelligd. + Ik heb een bestand of map verborgen. Hoe kan ik dit ongedaan maken? + Kies het menu-item \"Verborgen items tijdelijk tonen\", of schakel de instelling \"Verborgen items tonen\" in om het verborgen item te kunnen zien. Druk vervolgens lang op het item en kies \"Tonen\" om het verbergen ongedaan te maken. Mappen worden verborgen door het bestand \".nomedia\" in de map te plaatsen; dit bestand kan ook handmatig in een andere app worden verwijderd. diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index f1414d43c..fa6d862d1 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -31,6 +31,7 @@ Napraw datę utworzenia Naprawiam… Daty zostały naprawione + Share a resized version Filtruj multimedia @@ -87,7 +88,6 @@ Przewróć Przewróć w poziomie Przewróć w pionie - Edytuj w: Wolne Inny @@ -157,7 +157,6 @@    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 - Zamień funkcję udostępniania na obracanie w menu pełnoekranowym Dodatkowe szczegóły przy podglądzie pełnoekranowym Zarządzaj dodatkowymi szczegółami    Zezwalaj na powiększanie jednym palcem w widoku pełnoekranowym @@ -172,6 +171,7 @@ Pokazuj kosz jako ostatni element na głównym ekranie Zezwalaj na zamykanie pełnoekranowego widoku gestem pociągnięcia w dół Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures    Miniatury @@ -193,7 +193,6 @@    Przytrzymaj album(y) i wybierz ikonę przypięcia w pasku akcji.    Jak mogę przwijać filmy? 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. -    Kliknij na napisie z czasem trwania filmu, bądź tym z obecnym momentem filmu.    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? @@ -202,8 +201,6 @@    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. -    Zdjęcia w widoku pełnoekranowym mają dziwne artefakty. Jak mogę to naprawić? - W ustawieniach aplikacji włącz opcję \'Zamieniaj powiększalne obrazy na te o lepszej jakości\'. Poprawi ona jakość zdjęć, jednak przy bardzo dużych powiększeniach mogą się stać one zbyt rozmazane. 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 4e5ac0160..b2b49c576 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -31,6 +31,7 @@ Fix Date Taken value Fixing… Dates fixed successfully + Share a resized version Filtrar mídia @@ -87,7 +88,6 @@ Inverter Horizontalmente Verticalmente - Editar com Free Other @@ -157,7 +157,6 @@ Permitir controle do brilho com gestos na vertical Permitir controle do volume e brilho com gestos na vertical Mostrar quantidade de arquivos das pastas - Substituir botão "Compartilhar" por "Rotação de tela" quando em tela cheia Exibir detalhes extendidos quando em tela cheia Gerenciar detalhes extendidos Permitir zoom com um dedo quando em exibição de tela cheia @@ -172,6 +171,7 @@ Show the Recycle Bin as the last item on the main screen Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Miniaturas @@ -194,7 +194,6 @@ You can long press the desired album and select the Pin icon at the actionmenu, 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. - 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? @@ -204,8 +203,6 @@ 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. 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? diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 761f3a251..9706ec32d 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -31,6 +31,7 @@ Corrigir data de obtenção A corrigir… Dados corrigidos com sucesso + Share a resized version Filtrar multimédia @@ -87,7 +88,6 @@ Inverter Horizontalmente Verticalmente - Editar com Livre Outro @@ -116,7 +116,7 @@ Apresentação em ciclo Apresentação terminada Não foram encontrados ficheiros para a apresentação - Use crossfade animations + Utilizar animação de transição Tipo de exibição @@ -134,8 +134,8 @@ Extensão - Folder shown on the widget: - Show folder name + Pasta mostrada no widget: + Mostrar nome da pasta Reproduzir vídeos automaticamente @@ -157,7 +157,6 @@ 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 - Substituir a opção Partilhar pela opção Rodar se em ecrã completo Mostrar detalhes se em ecrã completo Gerir detalhes exibidos Permitir ampliação com um dedo se em ecrã completo @@ -171,7 +170,8 @@ Mostrar fotos com a melhor qualidade possível Mostrar a reciclagem como o último item do ecrã principal Sair de ecrã completo com um gesto para baixo - Allow 1:1 zooming in with two double taps + Permitir ampliação 1:1 com dois toques + Abrir vídeos em ecrã distinto com os novos toques horizontais Miniaturas @@ -194,7 +194,6 @@ You can long press the desired album and select the Pin icon at the actionmenu, 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. - 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? @@ -204,8 +203,6 @@ 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. 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? @@ -219,7 +216,7 @@ - An offline gallery for managing your files without ads, respecting your privacy. + Aplicação para gerir os seus ficheiros, sem anúncios e com total privacidade. Um aplicação capaz de mostrar diversos tipos de imagens e vídeos incluíndo SVG, RAW, fotos panorâmicas e vídeos. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 78999b471..2da3c8be5 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -31,6 +31,7 @@ Исправить дату Исправление… Даты исправлены + Share a resized version Фильтр медиа @@ -87,7 +88,6 @@ Отразить По горизонтали По вертикали - Редактировать в… Произвольно Другое @@ -157,7 +157,6 @@ Управление яркостью при просмотре изображения вертикальными жестами Управление громкостью и яркостью при просмотре видео вертикальными жестами Показывать количество файлов в папках - Заменить \"Поделиться\" на \"Повернуть\" в меню при просмотре изображения Показывать сведения о файле Выбор сведений о файле Масштабирование одним пальцем при просмотре изображения @@ -172,6 +171,7 @@ Показывать корзину как последний элемент на главном экране Выходить из полноэкранного режима жестом вниз Масштаб 1:1 двумя двойными нажатиями + Always open videos on a separate screen with new horizontal gestures Миниатюры @@ -194,7 +194,6 @@ Вы можете длительным нажатием на желаемый альбом открыть меню действий в нём выбрать пункт \"Закрепить\". Можно закрепить несколько альбомов (папок); прикреплённые элементы будут отсортированы по методу сортировки по умолчанию. Как ускорить перемотку видео? Вы можете либо перемещать пальцем по горизонтали над видеоплеером, либо нажать на цифры текущего положения или максимальной длительности видео рядом с панелью поиска, что приведёт к перемещению позиции воспроизведения назад или вперёд. - Вы можете нажать на цифры текущего положения или максимальной длительности видео рядом с панелью поиска, что приведёт к перемещению позиции воспроизведения либо назад, либо вперёд. В чём разница между скрытием и исключением папки? Исключение запрещает отображение папки только в Simple Gallery, в то время как скрытие работает системно и скрывает папку из других галерей. Это достигается путём создания пустого файла \".nomedia\" в данной папке, который впоследствии можно удалить любым файловым менеджером. Почему отображаются папки с музыкальными обложками? @@ -204,8 +203,6 @@ Что делать, если я хочу видеть только несколько конкретных папок? Добавление папки во включённые не исключает автоматически остальные. Что вы можете сделать это через \"Настройки\" -> \"Управление исключёнными папками\". Исключите корневую папку \"/\", затем добавьте нужные папки в \"Настройки\" -> \"Управление включёнными папками\". Это сделает видимыми только выбранные папки, так как исключение и включение являются рекурсивными, и если папка исключена и включена, то она будет отображаться. - Полноэкранные изображения имеют странные артефакты, можно как-то улучшить качество? - Да, в настройках есть переключатель \"Заменять масштабируемые изображения высококачественными\", использовуйте его. Это улучшит качество изображений, но они будут размыты, если вы попытаетесь сильно увеличить масштаб отображения. Можно ли обрезать изображения с помощью данного приложения? Да, вы можете обрезать изображения в редакторе, перетаскивая за углы. К редактированию можно перейти, выбрав соответсвующий пункт в меню, открывающемуся длительным нажатием на миниатюру или изображение в полноэкранном режиме. Могу ли я как-то сгруппировать миниатюры медиафайлов? diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index f8c929574..d9b61d146 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -31,6 +31,7 @@ Opraviť dátum vytvorenia Opravuje sa… Dátumy boli úspešne opravené + Zdieľať verziu so zmenenou veľkosťou Filter médií @@ -87,7 +88,6 @@ Preklopiť Preklopiť vodorovne Preklopiť zvisle - Upraviť s Voľný Iný @@ -157,7 +157,6 @@ Povoliť ovládanie jasu vertikálnymi ťahmi Povoliť ovládanie hlasitosti a jasu videí vertikálnymi ťahmi Zobraziť počet médií v priečinku na hlavnej obrazovke - Nahradiť Zdieľanie s Otočením v celoobrazovkovom menu Zobraziť rozšírené vlastnosti ponad celoobrazovkové médiá Spravovať rozšírené vlastnosti Povoliť približovanie jedným prstom v celoobrazovkovom režime @@ -172,6 +171,7 @@ Zobraziť odpadkový kôš ako poslednú položku na hlavnej obrazovke Povoliť zatváranie celoobrazovkového režimu potiahnutím prsta dole Povoliť 1:1 priblíženie dvojnásobným dvojklikom + Vždy otvárať videá na vlastnej obrazovke s novými vodorovnými gestami Náhľady @@ -194,7 +194,6 @@ Môžete označiť daný priečinok dlhým podržaním a zvoliť tlačidlo s obrázkom pripinačky, to ho pripne na vrch. Môžete pripnúť aj viacero priečinkov, budú zoradené podľa zvoleného radenia. Ako viem posunúť video vpred? Môžete to dosiahnuť vodorovným potiahnutím prsta cez video prehrávač, alebo kliknúť na texty súčasnej, alebo maximálnej dĺžky videa, ktoré sú vedľa indikátora súčasného progresu. To posunie video buď vpred, alebo vzad. - Môžete kliknúť na texty súčasnej, alebo maximálnej dĺžky videa, ktoré sú vedľa indikátora súčasného progresu. To posunie video buď vpred, alebo vzad. Aký je rozdiel medzi Skrytím a Vylúčením priečinka? Kým vylúčenie predíde zobrazeniu priečinka iba vrámci Jednoduchej Galérie, skrytie ho ukryje vrámci celého systému, teda to ovplyvní aj ostatné galérie. Skrytie funguje pomocou vytvorenia prázdneho \".nomedia\" súboru v danom priečinku, ktorý viete vymazať aj nejakým správcom súborov. Prečo sa mi zobrazujú priečinky s obalmi hudobných albumov, alebo nálepkami? @@ -204,8 +203,6 @@ Čo v prípade, ak chcem mať zobrazených iba pár priečinkov? Pridanie priečinka medzi Pridané Priečinky automaticky nevylúči ostatné. Môžete ale ísť do Nastavenia -> Spravovať vylúčené priečinky a zvoliť Koreňový priečinok \"/\", následne pridať žiadané priečinky v Nastavenia -> Spravovať pridané priečinky. To spôsobí, že budú zobrazené iba vyžiadané priečinky, keďže aj vylúčenie, aj pridanie fungujú rekurzívne a ak je priečinok vylúčený, aj pridaný, bude viditeľný. - Fotky na celú obrazovku majú zhoršenú kvalitu, viem ju nejak zlepšiť? - Áno, v nastaveniach je prepínač s textom \"Nahradiť hlboko priblížiteľné obrázky s obrázkami s lepšou kvalitou\", môžete ho skúsiť. Spôsobí to vyššiu kvalitu obrázkov, po priblížení sa ale budú rozmazávať oveľa skôr. Dá sa s touto aplikáciou orezať obrázky? Áno, orezanie je možné v editore, potiahnutím rohov obrázkov. Do editoru sa môžete dostať buď dlhým podržaním náhľadu obrázku a zvolením menu položky Upraviť, alebo zvolením Upraviť pri celoobrazovkovom režime. Viem nejakým spôsobom zoskupiť náhľady súborov? diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 8be442876..6ded38895 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -31,6 +31,7 @@ Popravi datum posnetka Popravljam… Datumi uspešno popravljeni + Share a resized version Filtriranje datotek @@ -87,9 +88,8 @@ Zrcaljenje Zrcali horizontalno Zrcali vertikalno - Uredi z Prosto - Other + Drugo Simple ozadje @@ -116,7 +116,7 @@ Ponavljaj diaprojekcijo Diaprojekcija se je zaključila Ne najdem datotek za diaprojekcijo - Use crossfade animations + Uporabi križanje animacij Spremeni tip pogleda @@ -134,8 +134,8 @@ Končnica - Folder shown on the widget: - Show folder name + Mapa uporabljena na pripomočku: + Prikaži ime mape Avtomatično predvajaj videoposnetke @@ -157,7 +157,6 @@ Dovoli nadzor svetlosti fotografije z vertikalnimi gestami Dovoli nadzor glasnosti in svetlosti videoposnetka z vertikalnimi gestami Pokaži število elementov v glavnem pogledu - Zamenjaj Deli z Obrni v celozaslonskem meniju Prikaži razširjene podrobnosti nad celozaslonskim prikazom Urejaj razširjene podrobnosti Dovoli enoprstno povečavo v celozaslonskem načinu @@ -171,7 +170,8 @@ Prikaži slike v največji možni kvaliteti Prikaži Koš kot zadnji element na glavnem zaslonu Dovoli zapiranje celozaslonskega načina z gesto navzdol - Allow 1:1 zooming in with two double taps + Dovoli 1:1 povečavo z dvojnim pritiskom + Vedno odpri videoposnetke na ločenem zaslonu z novimi horizontalnimi gestami Sličice @@ -194,7 +194,6 @@ Z dolgim pritiskom na album se vam prikaže meni, v katerem je na voljo bucika, s katero pripnete album na željeno mesto. Na ta način lahko pripnete več albumov, ki bodo razvrščeni v skladu s privzetim načinom razvrščanja. Ali lahko hitro predvajam videoposnetke? 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. - Lahko kliknete na napis trenutnega ali maksimalnega trajanja poleg vrstice položaja, kar premakne/preskoči video naprej ali nazaj. Kakšna je razlika med skrivanjem in izključevanjem mape? Izključevanje mape jo skrije le v Simple galeriji, medtem ko jo skrivanje skrije tudi v ostalih aplikacijah oz. galerijah. Deluje tako, da kreira prazno \".nomedia\" datoteko v izbrani mapi, katero lahko odstranite tudi s katerimkoli urejevalnikom datotek. Zakaj se v galeriji prikažejo datoteke z naslovnicami glasbenih map ali nalepk? @@ -204,8 +203,6 @@ Kaj, če želim prikazati le nekaj izbranih map? Dodajanje mape med vključene mape avtomatično ne izključi ničesar. Lahko pa naredite sledeče: v Nastavitvah -> Urejaj izključene mape izključite korensko mapo \"/\", željene mape pa dodajte v Nastavitvah -> Urejaj vključene mape. To bo naredilo vidne le vključene mape, saj sta tako vključevanje kot tudi izključevanje rekurzivna, kar pomeni, da je mapa, ki je istočasno izključena in vključena, vidna. - Celozaslonske slike imajo čuden izgled, lahko kako popravim kvaliteto? - Da, v Nastavitvah je opcija \"Nadomesti globoko povečljive slike z bolj kvalitetnimi\", ki jo lahko uporabite. To bo slike izboljšalo, vendar bodo te bolj zamegljene, ko jih boste želeli preveč povečati. Ali lahko obrezujem slike s to aplikacijo? Da, slike lahko obrezujete z vlečenjem kotov slike. Do urejevalnika lahko pridete z dolgim pritiskom na sličico fotografije in izborom opcije Uredi ali izborom funkcije Uredi iz celozaslonskega načina prikaza. Ali lahko združujem sličice medijskih datotek? @@ -218,7 +215,7 @@ Lahko uporabite funkcijo \"Začasno prikaži skrite elemente\", ki se nahaja v meniju na glavnem zaslonu ali preklopite \"Prikaži skrite elemente\" v Nastavitvah aplikacije. Če želite element označiti kot viden, z dolgim pritiskom nanj prikličite meni in izberite \"Prikaži\". Skrivanje map deluje tako, da se kreira prazno \".nomedia\" datoteko v izbrani mapi, ki jo lahko odstranite tudi s katerimkoli urejevalnikom datotek. - An offline gallery for managing your files without ads, respecting your privacy. + Galerija brez obvezne internetne povezave za urejanje vaših datotek brez prikazovanja oglasov in z upoštevanjem vaše zasebnosti. Visoko prilagodljiva galerija, zmožna prikazovanja različnih tipov fotografij in videoposnetkov, vključno s SVGji, RAWi, panoramskimi fotografijami in videoposnetki. diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index c2e6e6a9e..796a5a6c8 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -31,6 +31,7 @@ Korrigera fotodatum Korrigerar… Datumen har korrigerats + Share a resized version Filtrera media @@ -87,7 +88,6 @@ Vänd Vänd horisontellt Vänd vertikalt - Redigera med Fritt Other @@ -157,7 +157,6 @@ Tillåt styrning av fotoljusstyrka med vertikala gester Tillåt styrning av videovolym och videoljusstyrka med vertikala gester Visa antalet mediefiler i varje mapp i huvudvyn - Ersätt Dela med Rotera i helskärmsmenyn Visa utökad information över media i helskärmsläge Hantera utökad information Tillåt zoomning med ett finger när media visas i helskärmsläge @@ -172,6 +171,7 @@ Visa Papperskorgen som det sista objektet i huvudvyn Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Miniatyrer @@ -194,7 +194,6 @@ You can long press the desired album and select the Pin icon at the actionmenu, 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. - 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? @@ -204,8 +203,6 @@ 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. 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? diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 961371939..cab36d290 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -31,6 +31,7 @@ Çekilen tarih değerini düzelt Düzeltiliyor… Tarihler başarıyla düzeltildi + Share a resized version Medyayı filtrele @@ -87,7 +88,6 @@ Çevir Yatay olarak çevir Dikey olarak çevir - Şununla düzenle Serbest Other @@ -157,7 +157,6 @@ Dikey hareketlerle fotoğraf parlaklığının kontrolüne izin ver Video sesini ve parlaklığını dikey hareketlerle kontrol etmeye izin ver Ana görünümde klasör medya sayısını göster - Tam ekran menüsünde Döndür ile Paylaş\'ın yerini değiştir Tam ekran medya üzerinde genişletilmiş ayrıntıları göster Genişletilmiş ayrıntıları yönet Tam ekran medyalarda tek parmakla yakınlaştırmaya izin ver @@ -172,6 +171,7 @@ Geri dönüşüm kutusu\'nu ana ekranda son öğe olarak göster Tam ekran görünümünü aşağı hareketi ile kapatmaya izin ver Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Küçük resimler @@ -194,7 +194,6 @@ İstediğiniz albüme uzunca basabilir ve eylem menüsündeki Sabitle simgesini seçebilirsiniz. Birden çok klasörü de sabitleyebilirsiniz, sabitlenmiş öğeler varsayılan sıralama yöntemine göre sıralanır. Videoları nasıl hızlıca ileri sarabilirim? 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. - Videoyu geriye ya da ileriye taşıyacak olan arama çubuğunun yakınındaki geçerli veya maksimum süre metinlerini tıklayabilirsiniz. Klasörün gizlenmesi ve hariç tutulması arasındaki fark nedir? Hariç tut, klasörü yalnızca Basit Galeri\'de görüntülemeyi engellerken, Gizle sistem genelinde çalışır ve klasörü diğer galerilerden de gizler. Verilen klasörde boş bir \".nomedia\" dosyası oluşturarak çalışır, daha sonra herhangi bir dosya yöneticisi ile kaldırabilirsiniz. Neden albüm resimlerini içeren klasörler görünüyor? @@ -204,8 +203,6 @@ Sadece birkaç belirli klasörün görünmesini istersem ne olur? Dahil Edilen Klasörler\'e bir klasör eklemek otomatik olarak hiçbir şeyi hariç tutmaz. Yapabilecekleriniz Ayarlar -> Hariç Tutulan Klasörleri Yönet, kök klasörü \"/\" hariç tut, ardından Ayarlar -> Dahil Edilen Klasörleri Yönet. Bu, hem hariç tutulan hem de dahil edilen olmak üzere, yalnızca seçilen klasörleri görünür hale getirir ve bir klasör her ikisi de hariç tutulur ve dahil edilirse, görünür. - Tam ekran görüntülerde garip eserler var, bir şekilde kaliteyi artırabilir miyim? - Evet, Ayarlar\'da \"Daha iyi kalitede olanlar ile derin yakınlaştırılabilir resimleri değiştir\" diyen bir geçiş var. Bunu kullanabilirsiniz. Görüntülerin kalitesini artırır, ancak çok fazla zum yapmaya çalıştığınızda bulanıklaşır. Bu uygulamayla görüntüleri kırpabilir miyim? Evet, görüntü köşelerini sürükleyerek resimleri düzenleyicide kırpabilirsiniz. Düzenleyiciye, bir resim küçük resmine uzun basıp Düzenle\'yi seçerek veya tam ekran görünümünden Düzenle\'yi seçerek ulaşabilirsiniz. Medya dosyası küçük resimlerini bir şekilde gruplayabilir miyim? diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index e4f8f07dc..0099580ab 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -31,6 +31,7 @@ Виправити дату зйомки Виправлення… Дати успішно виправлені + Поділитися зображенням іншого розміру Фільтр мультимедійних файлів @@ -87,7 +88,6 @@ Віддзеркалити Віддзеркалити горизонтально Віддзеркалити вертикально - Редагувати за допомогою Вільне Інше @@ -157,7 +157,6 @@ Дозволити керування яскравістю фотографій вертикальними жестами Дозволити керування яскравістю та гучністю відео вертикальними жестами Показувати кількість файлів у теці на головному екрані - Замінити \"Поділитися\" на \"Обернути\" в повноекранному меню Показувати розширені подробиці при повноекранному перегляді Керування розширеними подробицями Дозволити масштабування одним пальцем при повноекранному перегляді @@ -172,6 +171,7 @@ Показувати \"Кошик\" останнім елементом на головному екрані Дозволити закриття повноекранного перегляду свайпом згори вниз Дозволити масштабування до 1:1 подвійним тапом + Завжди відкривати відео на окремому екрані з новими горизонтальними жестами Ескізи @@ -194,7 +194,6 @@ Ви можете виконати довге натискання на бажаному альбомі і вибрати піктограму \"Закріпити\" у меню дій, що закріпить його вгорі. Ви також можете закріпити декілька тек; закріплені елементи будуть відсортовані за методом сортування за-замовчуванням. Як я можу швидко прокручувати відео? Ви можете або провести пальцем горизонтально під час відтворення відео, або натиснути на текст поточної або максимальної тривалості відео біля прогрес-бару, що прокрутить відео або назад, або вперед. - Ви можете натиснути на текст поточного таймінгу або на текст загальної тривалості відео на прогрес-барі, що перемістить відео або назад, або вперед. В чому полягає різниця між приховуванням та виключенням теки? \"Виключити\" запобігає відображенню теки тільки в додатку Simple Gallery, в той час як \"Приховати\" працює на системному рівні і приховує теку і в інших галереях також. Це здійснюється шляхом створення порожнього файлу \".nomedia\" в заданій теці, який може бути видалений пізніше будь-яким файловим менеджером. Чому відображаються теки з музичними обкладинками або стікерами? @@ -204,8 +203,6 @@ Що робити, якщо я хочу, щоб лише кілька окремих тек були видимими? Додавання теки до \"Включених тек\" автоматично не виключає нічого. Що ви можете зробити, то це перейти в \"Налаштування\" -> \"Керування виключеними теками\", виключити кореневу теку \"/\", потім додати бажані теки через \"Налаштування\" -> \"Керування включеними теками\". Це зробить видимими лише обрані теки. Якщо тека є одночасно і виключеною, і включеною, вона відобразиться, оскільки і виключення, і включення є рекурсивним. - Повноекранні зображення мають дивні артефакти. Чи можна якось покращити якість? - Так, у \"Налаштуваннях\" є перемикач з текстом \"Замінити глибокомасштабовані зображення іншими кращої якості\", скористайтеся ним. Він покращить якість зображень, але вони будуть розмиватися, якщо ви занадто їх збільшуватимете. Чи можу я обрізати зображення у цьому додатку? Так, обрізати зображення можна у редакторі шляхом перетягування кутів зображення. Відкрити редактор можна або довгим натисканням на ескіз зображення і наступним вибором \"Редагувати\", або вибором \"Редагувати\" при повноекранному перегляді. Чи можу я якимось чином згрупувати ескізи медіафайлів? diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index abce63b4f..5226ef286 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -5,10 +5,10 @@ 编辑 打开相机 (隐藏) - (排除) + (排除) 锁定目录 解除锁定目录 - 锁定到顶部 + 固定到顶部 文件视图 所有目录 目录视图 @@ -31,6 +31,7 @@ 修复拍摄日期 正在修复… 日期修复成功 + 调整图像尺寸并分享 要显示的媒体文件 @@ -75,19 +76,18 @@ 保存 旋转 路径 - 无效图片路径 + 无效的图片路径 图片编辑失败 编辑方式: 未找到可用图片编辑器 未知的文件路径 - 不能覆盖源文件 + 无法覆盖源文件 向左旋转 向右旋转 旋转 180º 翻转 水平翻转 垂直翻转 - 编辑方式 自由 其他 @@ -116,7 +116,7 @@ 循环幻灯片 幻灯片结束 未发现可用媒体 - 使用交叉渐变动画 + 使用淡入淡出动画 更改视图类型 @@ -157,7 +157,6 @@ 使用纵向滑动手势控制照片亮度 使用纵向滑动手势控制视频音量和亮度 在主界面显示文件夹媒体计数 - 替换全屏时菜单栏的“分享”为“旋转” 全屏浏览媒体时显示详细信息 要显示的详细信息项目 单指缩放 @@ -172,6 +171,7 @@ 在主屏幕界面的最后一项显示回收站 使用下滑手势关闭全屏视图 双击两次后 1:1 放大图像 + 使用新的水平手势在独立页面播放视频 缩略图 @@ -193,7 +193,6 @@ 你可以长按该相册并在操作栏中点击图钉图标,这样 就可以将其固定在顶部了。你也可以固定多个文件夹,固定项目将按照默认排序方法排序。 如何快进/快退视频? 只需在视频播放器上左右滑动,或点击底栏进度条两侧的时间文本,即可前进或后退视频。 - 可以点击底栏进度条两侧的时间文本,或拖动进度条。 文件夹的隐藏和排除有什么区别? 排除功能只是防止其在简约图库中显示,而隐藏功能则使用的是系统的方法,这样做也会在其他图库中隐藏。它的工作原理是在给定的文件夹中创建一个空的.nomedia文件,你可以使用任何文件管理器删除它。 为什么会出现音乐艺术家封面或贴纸文件夹? @@ -202,8 +201,6 @@ 原因可能有很多,但解决方法很简单。只需进入设置 -> 管理包含目录,点击+号并选择到所需的文件夹。 如果我只想显示几个特定的文件夹,该如何操作? 在包含目录中添加文件夹不会自动排除其他的内容。你可以做的:进入设置 -> 管理排除目录,排除根目录\"/\",然后在设置 -> 管理包含目录中添加所需的文件夹。这样就只显示选定的文件夹了,由于排除和包含都是递归的,所以排除并包含的文件夹是会显示的。 - 全屏图像有些奇怪的东西,该如何提高画面质量? - 在设置中有一个“用质量更好的图像替换可深度缩放的图像”开关,打开它后就可以提高图像的显示质量,但是一旦尝试放大太多次,它们就又会变得模糊不清。 可以裁剪图片吗? 当然,通过长按图片缩略图并选择编辑,或在全屏视图中选择编辑来打开编辑器。你可以通过拖动图片边角来剪裁图像。 我能将媒体文件缩略图分组吗? diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index f342c0200..0c3413685 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -31,6 +31,7 @@ 修復拍照日期數值 修復中… 日期修復成功 + Share a resized version 篩選媒體檔案 @@ -87,7 +88,6 @@ 翻轉 水平翻轉 垂直翻轉 - 用其他程式編輯 自由 其它 @@ -116,7 +116,7 @@ 投影片循環 投影片結束 找不到投影片的媒體檔案 - Use crossfade animations + 使用淡入淡出動畫 改變瀏覽類型 @@ -139,7 +139,7 @@ 自動播放影片 - 記住影片上次撥放位置 + 記住影片上次播放位置 顯示檔案名稱 影片循環播放 縮圖顯示GIF動畫 @@ -157,7 +157,6 @@ 允許用上下手勢來控制相片的亮度 允許用上下手勢來控制影片的音量和亮度 主畫面顯示資料夾內的媒體檔案數量 - 將全螢幕選單的分享取代為旋轉 全螢幕時顯示詳細資訊 管理詳細資訊 全螢幕時允許單指縮放 @@ -172,6 +171,7 @@ 回收桶顯示在主畫面最後一項 允許用下滑手勢來關閉全螢幕檢視 允許用兩次雙擊來1:1縮放 + 總是用新的水平手勢在獨立畫面開啟影片 縮圖 @@ -193,8 +193,7 @@ 我如何讓某個相冊總是出現在頂端? 你可以長按想要的相冊,然後在操作選單中選擇[圖釘]圖示,就會釘選於頂端。你也能釘選多個資料夾,釘選的項目會依預設的排序方法來排序。 我如何快轉影片? - 你可以在影片撥放器上水平滑動你的手指,或者點擊進度條附近的當前或總時長文字。這會使影片快轉或倒轉。 - 你可以點擊進度條附近的當前或總時長文字,影片就會快轉或倒轉。 + 你可以在影片播放器上水平滑動你的手指,或者點擊進度條附近的當前或總時長文字。這會使影片快轉或倒轉。 隱藏和排除資料夾,兩者有什麼不同? [排除]只在簡易相簿中避免顯示出來;而[隱藏]則作用於整個系統,資料夾也會被其他相簿隱藏。這是藉由在指定資料夾內建立一個\".nomedia\"空白檔案來進行隱藏,你之後也能用任何檔案管理器移除。 為什麼有些音樂專輯封面或貼圖的資料夾會出現? @@ -204,8 +203,6 @@ 如果我只想看到幾個特定的資料夾,怎麼做? 在[包含資料夾]內添加資料夾並不會自動排除任何東西。你能做的是到[設定] -> [管理排除資料夾],排除根目錄 \"/\",然後在[設定] -> [管理包含資料夾]添加想要的資料夾。 那樣的話就只有選擇的資料夾可見。因為排除和包含都是遞迴的,如果一個資料夾被排除又被包含,則會顯示出來。 - 全螢幕圖片有雜訊,我有辦法提高品質嗎? - 可啊,[設定]內有個開關叫做「可深度縮放的圖片用品質更佳的來取代」,你能用用看。這會提高圖片的品質,不過一旦你放大太多就會模糊掉。 我可以用這程式裁減圖片嗎? 是的,你能夠在編輯器內拉動圖片角落來裁剪圖片。要進入編輯器,你可以長按圖片縮圖然後選擇[編輯],或是在全螢幕檢視下選擇[編輯]。 我可以歸類媒體檔案的縮圖嗎? diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index b2135537c..d9854752f 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -12,9 +12,14 @@ 50dp 72dp 64dp + 128dp + 164dp + 48dp 76dp 90dp + 98dp 180dp 86dp 110dp + 40dp diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index e0f0e33c6..0c2e2b267 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -2,6 +2,7 @@ + Reverted to the old way of opening videos, opening on separate screen can be enabled in the app settings Rewrote video playback, use a separate screen + added fast-forwarding with horizontal swiping\n Added optional 1:1 pixel ratio zooming with two double taps at fullscreen view\n diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 927dcba38..f6c49d687 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,6 +31,7 @@ Fix Date Taken value Fixing… Dates fixed successfully + Share a resized version Filter media @@ -87,7 +88,6 @@ Flip Flip horizontally Flip vertically - Edit with Free Other @@ -157,7 +157,6 @@ Allow controlling photo brightness with vertical gestures Allow controlling video volume and brightness with vertical gestures Show folder media count on the main view - Replace Share with Rotate at fullscreen menu Show extended details over fullscreen media Manage extended details Allow one finger zoom at fullscreen media @@ -172,6 +171,7 @@ Show the Recycle Bin as the last item on the main screen Allow closing the fullscreen view with a down gesture Allow 1:1 zooming in with two double taps + Always open videos on a separate screen with new horizontal gestures Thumbnails @@ -194,7 +194,6 @@ You can long press the desired album and select the Pin icon at the actionmenu, 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. - 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? @@ -204,8 +203,6 @@ 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. - Fullscreen images have weird artifacts, can I somehow improve the quality? - Yea, there is a toggle in Settings saying \"Replace deep zoomable images with better quality ones\", you can use that. It will improve the quality of the images, but they will get blurred once you try zooming in too much. 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? diff --git a/build.gradle b/build.gradle index d93366c1c..18eabc38b 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3e009998b..00616cb8d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Sep 26 14:42:41 CEST 2018 +#Wed Jan 16 16:59:58 CET 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip