Compare commits

...
5 Commits
Author SHA1 Message Date
OneWay 71ad849166 Remove the brightness dip in screen transition crossfades
- Fading the outgoing and incoming screens simultaneously makes content
  present on both (the camera FAB) dip to ~75% opacity mid-transition
- Fade only one layer: hold the outgoing destination opaque under the
  fading-in incoming one, and reveal the destination instantly under the
  fading-out one on back
2026-10-15 13:50:31 +08:00
OneWay 761db7a69d Keep the camera FAB stable across folder navigation
- Skip rendering the FAB until saved preferences load, so it is never
  drawn at the default corner and never jumps to its dragged position
- Share user preferences as one hot process-wide StateFlow instead of a
  cold disk read per screen, so a newly created gallery screen receives
  the FAB position synchronously in the ViewModel constructor
2026-10-15 13:50:31 +08:00
OneWay 428749d8a8 Show the gallery folder name from the first frame
- Carry the folder name through GalleryRoute into the ViewModel's
  SavedStateHandle, so the TopBar title is correct immediately on
  navigation, before any directory listing completes
- Seed a provisional name from the SAF URI segment in loadPhotos as a
  fallback for entry points without a name (after-camera navigation)
- Drop the 'Gallery' fallback title and the unused gallery_title string
2026-10-15 13:50:31 +08:00
OneWay 460c50bfd9 Fix photo viewer flicker when opening an image
- Keep the grid composed under the viewer instead of swapping it for a
  black box, removing the momentary black flash while the pager draws
  its first frame after tapping a photo
- Restore the pre-audit fade: thumbnail stays fully opaque under the
  fading-in full image instead of crossfading both over black
2026-10-15 13:50:31 +08:00
OneWay 5832e2db4a Replace launcher icon with adaptive-only vector glyph 2026-10-15 13:50:31 +08:00
18 changed files with 79 additions and 82 deletions

No files matched your search

@@ -9,8 +9,13 @@ import androidx.datastore.preferences.core.floatPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore import androidx.datastore.preferences.preferencesDataStore
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@@ -41,17 +46,26 @@ class UserPreferencesRepository @Inject constructor(
val SCREEN_TRANSITIONS_ENABLED = booleanPreferencesKey("screen_transitions_enabled") val SCREEN_TRANSITIONS_ENABLED = booleanPreferencesKey("screen_transitions_enabled")
} }
val userPreferencesFlow: Flow<UserPreferences> = context.dataStore.data.map { prefs -> // Hot, process-wide cache: the DataStore file is read once, and every screen
UserPreferences( // created later receives the current value synchronously on subscription,
rootFolderUri = prefs[Keys.ROOT_FOLDER_URI], // instead of re-reading disk per screen and flashing default positions.
cameraFabXFraction = prefs[Keys.CAMERA_FAB_X_FRACTION]?.coerceIn(0f, 1f) ?: 1f, val userPreferencesFlow: StateFlow<UserPreferences> = context.dataStore.data
cameraFabYFraction = prefs[Keys.CAMERA_FAB_Y_FRACTION]?.coerceIn(0f, 1f) ?: 1f, .map { prefs ->
gallerySortAscending = prefs[Keys.GALLERY_SORT_ASCENDING] ?: true, UserPreferences(
galleryGridMode = prefs[Keys.GALLERY_GRID_MODE] ?: true, rootFolderUri = prefs[Keys.ROOT_FOLDER_URI],
zipJpegCompression = prefs[Keys.ZIP_JPEG_COMPRESSION] ?: true, cameraFabXFraction = prefs[Keys.CAMERA_FAB_X_FRACTION]?.coerceIn(0f, 1f) ?: 1f,
screenTransitionsEnabled = prefs[Keys.SCREEN_TRANSITIONS_ENABLED] ?: true, cameraFabYFraction = prefs[Keys.CAMERA_FAB_Y_FRACTION]?.coerceIn(0f, 1f) ?: 1f,
gallerySortAscending = prefs[Keys.GALLERY_SORT_ASCENDING] ?: true,
galleryGridMode = prefs[Keys.GALLERY_GRID_MODE] ?: true,
zipJpegCompression = prefs[Keys.ZIP_JPEG_COMPRESSION] ?: true,
screenTransitionsEnabled = prefs[Keys.SCREEN_TRANSITIONS_ENABLED] ?: true,
)
}
.stateIn(
scope = CoroutineScope(SupervisorJob() + Dispatchers.IO),
started = SharingStarted.Eagerly,
initialValue = UserPreferences(),
) )
}
suspend fun setRootFolderUri(uri: String) { suspend fun setRootFolderUri(uri: String) {
context.dataStore.edit { prefs -> context.dataStore.edit { prefs ->
@@ -32,7 +32,10 @@ import kotlinx.serialization.Serializable
object FoldersRoute object FoldersRoute
@Serializable @Serializable
data class GalleryRoute(val folderUri: String) data class GalleryRoute(
val folderUri: String,
val folderName: String = "",
)
@Serializable @Serializable
data class CameraRoute( data class CameraRoute(
@@ -64,14 +67,20 @@ fun OneCameraNavGraph(navController: NavHostController) {
navController = navController, navController = navController,
startDestination = FoldersRoute, startDestination = FoldersRoute,
enterTransition = { if (transitionsEnabled) fadeIn(tween(250)) else EnterTransition.None }, enterTransition = { if (transitionsEnabled) fadeIn(tween(250)) else EnterTransition.None },
exitTransition = { if (transitionsEnabled) fadeOut(tween(250)) else ExitTransition.None }, exitTransition = {
popEnterTransition = { if (transitionsEnabled) fadeIn(tween(250)) else EnterTransition.None }, if (transitionsEnabled) {
ExitTransition.KeepUntilTransitionsFinished
} else {
ExitTransition.None
}
},
popEnterTransition = { EnterTransition.None },
popExitTransition = { if (transitionsEnabled) fadeOut(tween(250)) else ExitTransition.None }, popExitTransition = { if (transitionsEnabled) fadeOut(tween(250)) else ExitTransition.None },
) { ) {
composable<FoldersRoute> { composable<FoldersRoute> {
FoldersScreen( FoldersScreen(
onNavigateToGallery = { folderUri -> onNavigateToGallery = { folderUri, folderName ->
navController.navigate(GalleryRoute(folderUri)) navController.navigate(GalleryRoute(folderUri, folderName))
}, },
onNavigateToCamera = { folderUri -> onNavigateToCamera = { folderUri ->
navController.navigate( navController.navigate(
@@ -93,8 +102,8 @@ fun OneCameraNavGraph(navController: NavHostController) {
onNavigateToCamera = { folderUri -> onNavigateToCamera = { folderUri ->
navController.navigate(CameraRoute(folderUri)) navController.navigate(CameraRoute(folderUri))
}, },
onNavigateToSubfolder = { folderUri -> onNavigateToSubfolder = { folderUri, folderName ->
navController.navigate(GalleryRoute(folderUri)) navController.navigate(GalleryRoute(folderUri, folderName))
}, },
onNavigateBack = { navController.popBackStack() }, onNavigateBack = { navController.popBackStack() },
) )
@@ -57,7 +57,7 @@ import com.example.onecamera.ui.components.oneCameraTopAppBarColors
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable @Composable
fun FoldersScreen( fun FoldersScreen(
onNavigateToGallery: (String) -> Unit, onNavigateToGallery: (folderUri: String, folderName: String) -> Unit,
onNavigateToCamera: (String) -> Unit, onNavigateToCamera: (String) -> Unit,
onNavigateToSettings: () -> Unit, onNavigateToSettings: () -> Unit,
viewModel: FoldersViewModel = hiltViewModel(), viewModel: FoldersViewModel = hiltViewModel(),
@@ -230,7 +230,7 @@ fun FoldersScreen(
onClick = { onClick = {
viewModel.prefetchFolderForNavigation(folder.uri.toString()) viewModel.prefetchFolderForNavigation(folder.uri.toString())
onNavigateToGallery(folder.uri.toString()) onNavigateToGallery(folder.uri.toString(), folder.name)
}, },
onCompress = { viewModel.zipFolderAndShare(folder) }, onCompress = { viewModel.zipFolderAndShare(folder) },
onCompressJpeg85 = { onCompressJpeg85 = {
@@ -49,8 +49,8 @@ import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
@@ -93,7 +93,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged
fun GalleryScreen( fun GalleryScreen(
folderUri: String, folderUri: String,
onNavigateToCamera: (String) -> Unit, onNavigateToCamera: (String) -> Unit,
onNavigateToSubfolder: (String) -> Unit, onNavigateToSubfolder: (folderUri: String, folderName: String) -> Unit,
onNavigateBack: () -> Unit, onNavigateBack: () -> Unit,
viewModel: GalleryViewModel = hiltViewModel(), viewModel: GalleryViewModel = hiltViewModel(),
) { ) {
@@ -281,9 +281,7 @@ fun GalleryScreen(
title = { title = {
Column { Column {
Text( Text(
uiState.folderName.ifEmpty { uiState.folderName,
stringResource(R.string.gallery_title)
},
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
@@ -408,14 +406,6 @@ fun GalleryScreen(
Box(modifier = Modifier.fillMaxSize()) { Box(modifier = Modifier.fillMaxSize()) {
when { when {
uiState.selectedPhoto != null -> {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black),
)
}
!uiState.viewPreferencesLoaded -> { !uiState.viewPreferencesLoaded -> {
Box(modifier = Modifier.fillMaxSize()) Box(modifier = Modifier.fillMaxSize())
} }
@@ -442,7 +432,7 @@ fun GalleryScreen(
onFolderClick = { onFolderClick = {
viewModel.prefetchFolderForNavigation(it.uri.toString()) viewModel.prefetchFolderForNavigation(it.uri.toString())
onNavigateToSubfolder(it.uri.toString()) onNavigateToSubfolder(it.uri.toString(), it.name)
}, },
onFolderCompress = { viewModel.zipFolderAndShare(it) }, onFolderCompress = { viewModel.zipFolderAndShare(it) },
onFolderCompressJpeg85 = { viewModel.zipFolderCompressedJpegsAndShare(it) }, onFolderCompressJpeg85 = { viewModel.zipFolderCompressedJpegsAndShare(it) },
@@ -484,12 +474,14 @@ fun GalleryScreen(
enter = fadeIn(tween(250)), enter = fadeIn(tween(250)),
exit = fadeOut(tween(150)), exit = fadeOut(tween(150)),
) { ) {
DraggableCameraFab( if (uiState.viewPreferencesLoaded) {
xFraction = uiState.cameraFabXFraction, DraggableCameraFab(
yFraction = uiState.cameraFabYFraction, xFraction = uiState.cameraFabXFraction,
onPositionChange = viewModel::saveCameraFabPosition, yFraction = uiState.cameraFabYFraction,
onClick = { onNavigateToCamera(uiState.currentFolderUri ?: folderUri) }, onPositionChange = viewModel::saveCameraFabPosition,
) onClick = { onNavigateToCamera(uiState.currentFolderUri ?: folderUri) },
)
}
} }
SelectionActionsBar( SelectionActionsBar(
@@ -670,16 +662,16 @@ private fun ZoomablePhoto(
Box(modifier = modifier.fillMaxSize()) { Box(modifier = modifier.fillMaxSize()) {
AsyncImage( if (fullAlpha < 1f) {
model = remember(photo.uri, context, fadeMs) { AsyncImage(
thumbnailDraftRequest(context, photo.uri, crossfadeMillis = fadeMs) model = remember(photo.uri, context, fadeMs) {
}, thumbnailDraftRequest(context, photo.uri, crossfadeMillis = fadeMs)
contentDescription = null, },
contentScale = ContentScale.Fit, contentDescription = null,
modifier = Modifier contentScale = ContentScale.Fit,
.fillMaxSize() modifier = Modifier.fillMaxSize(),
.graphicsLayer { alpha = 1f - fullAlpha }, )
) }
CoilZoomAsyncImage( CoilZoomAsyncImage(
model = fullImageRequest, model = fullImageRequest,
contentDescription = photo.name, contentDescription = photo.name,
@@ -688,7 +680,7 @@ private fun ZoomablePhoto(
onError = { isFullReady = false }, onError = { isFullReady = false },
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.graphicsLayer { alpha = fullAlpha }, .alpha(fullAlpha),
zoomState = zoomState, zoomState = zoomState,
) )
} }
@@ -4,6 +4,7 @@ import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import coil3.SingletonImageLoader import coil3.SingletonImageLoader
@@ -113,6 +114,7 @@ data class GalleryUiState(
@HiltViewModel @HiltViewModel
class GalleryViewModel @Inject constructor( class GalleryViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val preferencesRepository: UserPreferencesRepository, private val preferencesRepository: UserPreferencesRepository,
private val listGalleryUseCase: ListGalleryUseCase, private val listGalleryUseCase: ListGalleryUseCase,
private val listFolderTreeUseCase: ListFolderTreeUseCase, private val listFolderTreeUseCase: ListFolderTreeUseCase,
@@ -128,7 +130,11 @@ class GalleryViewModel @Inject constructor(
) : ViewModel() { ) : ViewModel() {
val uiState: StateFlow<GalleryUiState> val uiState: StateFlow<GalleryUiState>
field: MutableStateFlow<GalleryUiState> = MutableStateFlow(GalleryUiState()) field: MutableStateFlow<GalleryUiState> = MutableStateFlow(
// Navigation puts type-safe route args into the SavedStateHandle, so the
// title is correct from the very first frame, before any listing completes.
GalleryUiState(folderName = savedStateHandle.get<String>("folderName").orEmpty()),
)
private var forceReload = false private var forceReload = false
@@ -199,6 +205,9 @@ class GalleryViewModel @Inject constructor(
loadJob = viewModelScope.launch { loadJob = viewModelScope.launch {
uiState.value = uiState.value.copy( uiState.value = uiState.value.copy(
currentFolderUri = folderUriString, currentFolderUri = folderUriString,
folderName = state.folderName.ifEmpty {
folderUriString.substringAfterLast(':').substringAfterLast('/')
},
isLoading = true, isLoading = true,
error = null, error = null,
) )
@@ -4,20 +4,7 @@
android:height="108dp" android:height="108dp"
android:viewportWidth="108" android:viewportWidth="108"
android:viewportHeight="108"> android:viewportHeight="108">
<path <path
android:strokeColor="#000000" android:fillColor="#C9584D"
android:strokeWidth="3.375" android:pathData="M66.90,53.85C66.90,54.93 66.82,56.08 66.67,57.08C66.53,58.07 66.30,58.95 66.00,59.80C65.71,60.66 65.34,61.46 64.91,62.20C64.48,62.94 63.97,63.63 63.41,64.25C62.86,64.87 62.23,65.42 61.56,65.90C60.89,66.38 60.16,66.79 59.39,67.11C58.61,67.44 57.82,67.69 56.92,67.85C56.02,68.02 54.97,68.10 54.00,68.10C53.03,68.10 51.98,68.02 51.08,67.85C50.18,67.69 49.39,67.44 48.61,67.11C47.84,66.79 47.11,66.38 46.44,65.90C45.77,65.42 45.14,64.87 44.59,64.25C44.03,63.63 43.52,62.94 43.09,62.20C42.66,61.46 42.29,60.66 42.00,59.80C41.70,58.95 41.47,58.07 41.33,57.08C41.18,56.08 41.10,54.93 41.10,53.85C41.10,52.77 41.18,51.62 41.33,50.62C41.47,49.63 41.70,48.75 42.00,47.90C42.29,47.04 42.66,46.24 43.09,45.50C43.52,44.76 44.03,44.07 44.59,43.45C45.14,42.83 45.77,42.28 46.44,41.80C47.11,41.32 47.84,40.91 48.61,40.59C49.39,40.26 50.18,40.01 51.08,39.85C51.98,39.68 53.03,39.60 54.00,39.60C54.97,39.60 56.02,39.68 56.92,39.85C57.82,40.01 58.61,40.26 59.39,40.59C60.16,40.91 60.89,41.32 61.56,41.80C62.23,42.28 62.86,42.83 63.41,43.45C63.97,44.07 64.48,44.76 64.91,45.50C65.34,46.24 65.71,47.04 66.00,47.90C66.30,48.75 66.53,49.63 66.67,50.62C66.82,51.62 66.90,52.77 66.90,53.85ZM61.50,54.00C61.50,53.30 61.46,52.54 61.37,51.90C61.29,51.25 61.16,50.67 60.99,50.12C60.82,49.56 60.61,49.03 60.36,48.55C60.12,48.07 59.83,47.62 59.51,47.21C59.20,46.81 58.84,46.45 58.46,46.14C58.08,45.83 57.66,45.56 57.22,45.35C56.78,45.13 56.33,44.97 55.81,44.86C55.30,44.75 54.70,44.70 54.15,44.70C53.60,44.70 53.00,44.75 52.49,44.86C51.97,44.97 51.52,45.13 51.08,45.35C50.64,45.56 50.22,45.83 49.84,46.14C49.46,46.45 49.10,46.81 48.79,47.21C48.47,47.62 48.18,48.07 47.94,48.55C47.69,49.03 47.48,49.56 47.31,50.12C47.14,50.67 47.01,51.25 46.93,51.90C46.84,52.54 46.80,53.30 46.80,54.00C46.80,54.70 46.84,55.46 46.93,56.10C47.01,56.75 47.14,57.33 47.31,57.88C47.48,58.44 47.69,58.97 47.94,59.45C48.18,59.93 48.47,60.38 48.79,60.79C49.10,61.19 49.46,61.55 49.84,61.86C50.22,62.17 50.64,62.44 51.08,62.65C51.52,62.87 51.97,63.03 52.49,63.14C53.00,63.25 53.60,63.30 54.15,63.30C54.70,63.30 55.30,63.25 55.81,63.14C56.33,63.03 56.78,62.87 57.22,62.65C57.66,62.44 58.08,62.17 58.46,61.86C58.84,61.55 59.20,61.19 59.51,60.79C59.83,60.38 60.12,59.93 60.36,59.45C60.61,58.97 60.82,58.44 60.99,57.88C61.16,57.33 61.29,56.75 61.37,56.10C61.46,55.46 61.50,54.70 61.50,54.00Z" />
android:strokeLineJoin="round"
android:pathData="M 43.453125 32.90625 L 64.546875 32.90625 a 10.546875 10.546875 0 0 1 10.546875 10.546875 L 75.09375 64.546875 a 10.546875 10.546875 0 0 1 -10.546875 10.546875 L 43.453125 75.09375 a 10.546875 10.546875 0 0 1 -10.546875 -10.546875 L 32.90625 43.453125 a 10.546875 10.546875 0 0 1 10.546875 -10.546875 Z" />
<path
android:strokeColor="#000000"
android:strokeWidth="3.375"
android:pathData="M 41.34375 54 a 12.65625 12.65625 0 1 0 25.3125 0 a 12.65625 12.65625 0 1 0 -25.3125 0 Z" />
<path
android:fillColor="#d94e47"
android:pathData="M 68.71875 38.390625 a 2.53125 2.53125 0 1 0 5.0625 0 a 2.53125 2.53125 0 1 0 -5.0625 0 Z" />
</vector> </vector>
@@ -4,20 +4,7 @@
android:height="108dp" android:height="108dp"
android:viewportWidth="108" android:viewportWidth="108"
android:viewportHeight="108"> android:viewportHeight="108">
<path
android:strokeColor="#FFFFFF"
android:strokeWidth="3.375"
android:strokeLineJoin="round"
android:pathData="M 43.453125 32.90625 L 64.546875 32.90625 a 10.546875 10.546875 0 0 1 10.546875 10.546875 L 75.09375 64.546875 a 10.546875 10.546875 0 0 1 -10.546875 10.546875 L 43.453125 75.09375 a 10.546875 10.546875 0 0 1 -10.546875 -10.546875 L 32.90625 43.453125 a 10.546875 10.546875 0 0 1 10.546875 -10.546875 Z" />
<path
android:strokeColor="#FFFFFF"
android:strokeWidth="3.375"
android:pathData="M 41.34375 54 a 12.65625 12.65625 0 1 0 25.3125 0 a 12.65625 12.65625 0 1 0 -25.3125 0 Z" />
<path <path
android:fillColor="#FFFFFF" android:fillColor="#FFFFFF"
android:pathData="M 67.5 38.390625 a 2.109375 2.109375 0 1 0 4.21875 0 a 2.109375 2.109375 0 1 0 -4.21875 0 Z" /> android:pathData="M66.90,53.85C66.90,54.93 66.82,56.08 66.67,57.08C66.53,58.07 66.30,58.95 66.00,59.80C65.71,60.66 65.34,61.46 64.91,62.20C64.48,62.94 63.97,63.63 63.41,64.25C62.86,64.87 62.23,65.42 61.56,65.90C60.89,66.38 60.16,66.79 59.39,67.11C58.61,67.44 57.82,67.69 56.92,67.85C56.02,68.02 54.97,68.10 54.00,68.10C53.03,68.10 51.98,68.02 51.08,67.85C50.18,67.69 49.39,67.44 48.61,67.11C47.84,66.79 47.11,66.38 46.44,65.90C45.77,65.42 45.14,64.87 44.59,64.25C44.03,63.63 43.52,62.94 43.09,62.20C42.66,61.46 42.29,60.66 42.00,59.80C41.70,58.95 41.47,58.07 41.33,57.08C41.18,56.08 41.10,54.93 41.10,53.85C41.10,52.77 41.18,51.62 41.33,50.62C41.47,49.63 41.70,48.75 42.00,47.90C42.29,47.04 42.66,46.24 43.09,45.50C43.52,44.76 44.03,44.07 44.59,43.45C45.14,42.83 45.77,42.28 46.44,41.80C47.11,41.32 47.84,40.91 48.61,40.59C49.39,40.26 50.18,40.01 51.08,39.85C51.98,39.68 53.03,39.60 54.00,39.60C54.97,39.60 56.02,39.68 56.92,39.85C57.82,40.01 58.61,40.26 59.39,40.59C60.16,40.91 60.89,41.32 61.56,41.80C62.23,42.28 62.86,42.83 63.41,43.45C63.97,44.07 64.48,44.76 64.91,45.50C65.34,46.24 65.71,47.04 66.00,47.90C66.30,48.75 66.53,49.63 66.67,50.62C66.82,51.62 66.90,52.77 66.90,53.85ZM61.50,54.00C61.50,53.30 61.46,52.54 61.37,51.90C61.29,51.25 61.16,50.67 60.99,50.12C60.82,49.56 60.61,49.03 60.36,48.55C60.12,48.07 59.83,47.62 59.51,47.21C59.20,46.81 58.84,46.45 58.46,46.14C58.08,45.83 57.66,45.56 57.22,45.35C56.78,45.13 56.33,44.97 55.81,44.86C55.30,44.75 54.70,44.70 54.15,44.70C53.60,44.70 53.00,44.75 52.49,44.86C51.97,44.97 51.52,45.13 51.08,45.35C50.64,45.56 50.22,45.83 49.84,46.14C49.46,46.45 49.10,46.81 48.79,47.21C48.47,47.62 48.18,48.07 47.94,48.55C47.69,49.03 47.48,49.56 47.31,50.12C47.14,50.67 47.01,51.25 46.93,51.90C46.84,52.54 46.80,53.30 46.80,54.00C46.80,54.70 46.84,55.46 46.93,56.10C47.01,56.75 47.14,57.33 47.31,57.88C47.48,58.44 47.69,58.97 47.94,59.45C48.18,59.93 48.47,60.38 48.79,60.79C49.10,61.19 49.46,61.55 49.84,61.86C50.22,62.17 50.64,62.44 51.08,62.65C51.52,62.87 51.97,63.03 52.49,63.14C53.00,63.25 53.60,63.30 54.15,63.30C54.70,63.30 55.30,63.25 55.81,63.14C56.33,63.03 56.78,62.87 57.22,62.65C57.66,62.44 58.08,62.17 58.46,61.86C58.84,61.55 59.20,61.19 59.51,60.79C59.83,60.38 60.12,59.93 60.36,59.45C60.61,58.97 60.82,58.44 60.99,57.88C61.16,57.33 61.29,56.75 61.37,56.10C61.46,55.46 61.50,54.70 61.50,54.00Z" />
</vector> </vector>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

-1
View File
@@ -46,7 +46,6 @@
<item quantity="other">%d photos</item> <item quantity="other">%d photos</item>
</plurals> </plurals>
<string name="gallery_title">Gallery</string>
<string name="gallery_create_subfolder">Create subfolder</string> <string name="gallery_create_subfolder">Create subfolder</string>
<string name="gallery_sort_ascending">Sort ascending</string> <string name="gallery_sort_ascending">Sort ascending</string>
<string name="gallery_sort_descending">Sort descending</string> <string name="gallery_sort_descending">Sort descending</string>