Skip to content

Commit da47344

Browse files
authored
Gallery Detail Clipboard (#71)
* Gallery Detail Clipboard :: Patch 1 * Update ClipboardExtensions.kt
1 parent 4659409 commit da47344

File tree

5 files changed

+106
-6
lines changed

5 files changed

+106
-6
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.shifthackz.aisdv1.core.common.extensions
2+
3+
import android.content.ClipData
4+
import android.content.ClipboardManager
5+
import android.content.Context
6+
7+
fun Context.copyToClipboard(text: CharSequence) {
8+
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
9+
val clip = ClipData.newPlainText("label", text)
10+
clipboard.setPrimaryClip(clip)
11+
}

domain/src/main/java/com/shifthackz/aisdv1/domain/feature/ad/AdFeature.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,14 @@ interface AdFeature {
1818
val isEmpty: Boolean
1919
get() = id.isEmpty() || view == null
2020
}
21+
22+
companion object {
23+
val empty = object : AdFeature {
24+
override fun initialize(activity: Activity) = Unit
25+
override fun getHomeScreenBannerAd(context: Context) = Ad()
26+
override fun getGalleryDetailBannerAd(context: Context) = Ad()
27+
override fun loadAd(ad: Ad) = Unit
28+
override fun showRewardedCoinsAd(activity: Activity, rewardCallback: (Int) -> Unit) = Unit
29+
}
30+
}
2131
}

presentation/src/main/java/com/shifthackz/aisdv1/presentation/activity/AiStableDiffusionActivity.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import androidx.navigation.compose.NavHost
1515
import androidx.navigation.compose.composable
1616
import androidx.navigation.compose.rememberNavController
1717
import androidx.navigation.navArgument
18+
import com.shifthackz.aisdv1.core.common.extensions.copyToClipboard
1819
import com.shifthackz.aisdv1.core.common.extensions.openMarket
1920
import com.shifthackz.aisdv1.core.common.extensions.openUrl
2021
import com.shifthackz.aisdv1.core.common.file.FileProviderDescriptor
@@ -226,6 +227,7 @@ class AiStableDiffusionActivity : ComponentActivity(), ImagePickerFeature, FileS
226227
state = uiState,
227228
)
228229
},
230+
copyToClipboard = { text -> copyToClipboard(text) }
229231
).Build()
230232
}
231233

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.shifthackz.aisdv1.presentation.screen.gallery.detail
2+
3+
import android.graphics.Bitmap
4+
import com.shifthackz.aisdv1.core.model.asUiText
5+
import com.shifthackz.aisdv1.domain.entity.AiGenerationResult
6+
7+
val mockGalleryDetailTxt2Img = GalleryDetailState.Content(
8+
tabs = listOf(
9+
GalleryDetailState.Tab.IMAGE,
10+
GalleryDetailState.Tab.INFO
11+
),
12+
selectedTab = GalleryDetailState.Tab.IMAGE,
13+
generationType = AiGenerationResult.Type.TEXT_TO_IMAGE,
14+
id = 0L,
15+
bitmap = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888),
16+
inputBitmap = null,
17+
cfgScale = "0.7".asUiText(),
18+
createdAt = "01.01.1970".asUiText(),
19+
type = "txt2img".asUiText(),
20+
prompt = "input".asUiText(),
21+
negativePrompt = "output".asUiText(),
22+
size = "512x512".asUiText(),
23+
samplingSteps = "12".asUiText(),
24+
restoreFaces = "false".asUiText(),
25+
sampler = "Euler A".asUiText(),
26+
seed = "0000".asUiText(),
27+
subSeed = "0001".asUiText(),
28+
subSeedStrength = "".asUiText(),
29+
denoisingStrength = "".asUiText(),
30+
)

presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/gallery/detail/GalleryDetailScreen.kt

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.*
88
import androidx.compose.foundation.rememberScrollState
99
import androidx.compose.foundation.verticalScroll
1010
import androidx.compose.material.icons.Icons
11+
import androidx.compose.material.icons.filled.ContentCopy
1112
import androidx.compose.material.icons.outlined.ArrowBack
1213
import androidx.compose.material3.*
1314
import androidx.compose.runtime.Composable
@@ -17,6 +18,7 @@ import androidx.compose.ui.graphics.ColorFilter
1718
import androidx.compose.ui.res.painterResource
1819
import androidx.compose.ui.res.stringResource
1920
import androidx.compose.ui.text.style.TextAlign
21+
import androidx.compose.ui.tooling.preview.Preview
2022
import androidx.compose.ui.unit.dp
2123
import androidx.lifecycle.compose.collectAsStateWithLifecycle
2224
import com.shifthackz.aisdv1.core.model.UiText
@@ -32,14 +34,14 @@ import com.shifthackz.aisdv1.presentation.widget.image.ZoomableImage
3234
import com.shifthackz.aisdv1.presentation.widget.image.ZoomableImageSource
3335
import org.koin.core.component.KoinComponent
3436
import org.koin.core.component.inject
35-
3637
import java.io.File
3738

3839
class GalleryDetailScreen(
3940
private val viewModel: GalleryDetailViewModel,
4041
private val onNavigateBack: () -> Unit = {},
4142
private val shareGalleryFile: (File) -> Unit = {},
4243
private val shareGenerationParams: (GalleryDetailState) -> Unit = {},
44+
private val copyToClipboard: (CharSequence) -> Unit = {},
4345
) : MviScreen<GalleryDetailState, GalleryDetailEffect>(viewModel), KoinComponent {
4446

4547
private val adFeature: AdFeature by inject()
@@ -52,6 +54,7 @@ class GalleryDetailScreen(
5254
adFeature = adFeature,
5355
onNavigateBack = onNavigateBack,
5456
onTabSelected = viewModel::selectTab,
57+
onCopyTextClick = copyToClipboard,
5558
onSendToTxt2Img = viewModel::sendPromptToTxt2Img,
5659
onSendToImg2Img = viewModel::sendPromptToImg2Img,
5760
onExportImageToolbarClick = viewModel::share,
@@ -72,9 +75,10 @@ class GalleryDetailScreen(
7275
private fun ScreenContent(
7376
modifier: Modifier = Modifier,
7477
state: GalleryDetailState,
75-
adFeature: AdFeature,
78+
adFeature: AdFeature = AdFeature.empty,
7679
onNavigateBack: () -> Unit = {},
7780
onTabSelected: (GalleryDetailState.Tab) -> Unit = {},
81+
onCopyTextClick: (CharSequence) -> Unit = {},
7882
onSendToTxt2Img: () -> Unit = {},
7983
onSendToImg2Img: () -> Unit = {},
8084
onExportImageToolbarClick: () -> Unit = {},
@@ -130,6 +134,7 @@ private fun ScreenContent(
130134
onSendToImg2Img = onSendToImg2Img,
131135
onDeleteButtonClick = onDeleteButtonClick,
132136
onExportParamsClick = onExportParamsClick,
137+
onCopyTextClick = onCopyTextClick,
133138
)
134139
is GalleryDetailState.Loading -> Unit
135140
}
@@ -197,6 +202,7 @@ private fun GalleryDetailContentState(
197202
onSendToImg2Img: () -> Unit = {},
198203
onDeleteButtonClick: () -> Unit = {},
199204
onExportParamsClick: (GalleryDetailState.Content) -> Unit = {},
205+
onCopyTextClick: (CharSequence) -> Unit = {},
200206
) {
201207
Column(
202208
modifier = modifier,
@@ -219,6 +225,7 @@ private fun GalleryDetailContentState(
219225
onSendToImg2Img = onSendToImg2Img,
220226
onDeleteButtonClick = onDeleteButtonClick,
221227
onExportParamsClick = onExportParamsClick,
228+
onCopyTextClick = onCopyTextClick,
222229
)
223230
}
224231
}
@@ -232,6 +239,7 @@ private fun GalleryDetailsTable(
232239
onSendToImg2Img: () -> Unit = {},
233240
onDeleteButtonClick: () -> Unit = {},
234241
onExportParamsClick: (GalleryDetailState.Content) -> Unit = {},
242+
onCopyTextClick: (CharSequence) -> Unit = {},
235243
) {
236244
Scaffold(
237245
content = { paddingValues ->
@@ -251,88 +259,101 @@ private fun GalleryDetailsTable(
251259
name = R.string.gallery_info_field_date.asUiText(),
252260
value = state.createdAt,
253261
color = colorOddText,
262+
onCopyTextClick = onCopyTextClick,
254263
)
255264
GalleryDetailRow(
256265
modifier = Modifier.background(color = colorEvenBg),
257266
name = R.string.gallery_info_field_type.asUiText(),
258267
value = state.type,
259268
color = colorEvenText,
269+
onCopyTextClick = onCopyTextClick,
260270
)
261271
GalleryDetailRow(
262272
modifier = Modifier.background(color = colorOddBg),
263273
name = R.string.gallery_info_field_prompt.asUiText(),
264274
value = state.prompt,
265275
color = colorOddText,
276+
onCopyTextClick = onCopyTextClick,
266277
)
267278
GalleryDetailRow(
268279
modifier = Modifier.background(color = colorEvenBg),
269280
name = R.string.gallery_info_field_negative_prompt.asUiText(),
270281
value = state.negativePrompt,
271282
color = colorEvenText,
283+
onCopyTextClick = onCopyTextClick,
272284
)
273285
GalleryDetailRow(
274286
modifier = Modifier.background(color = colorOddBg),
275287
name = R.string.gallery_info_field_size.asUiText(),
276288
value = state.size,
277289
color = colorOddText,
290+
onCopyTextClick = onCopyTextClick,
278291
)
279292
GalleryDetailRow(
280293
modifier = Modifier.background(color = colorEvenBg),
281294
name = R.string.gallery_info_field_sampling_steps.asUiText(),
282295
value = state.samplingSteps,
283296
color = colorEvenText,
297+
onCopyTextClick = onCopyTextClick,
284298
)
285299
GalleryDetailRow(
286300
modifier = Modifier.background(color = colorOddBg),
287301
name = R.string.gallery_info_field_cfg.asUiText(),
288302
value = state.cfgScale,
289303
color = colorOddText,
304+
onCopyTextClick = onCopyTextClick,
290305
)
291306
GalleryDetailRow(
292307
modifier = Modifier.background(color = colorEvenBg),
293308
name = R.string.gallery_info_field_restore_faces.asUiText(),
294309
value = state.restoreFaces,
295310
color = colorEvenText,
311+
onCopyTextClick = onCopyTextClick,
296312
)
297313
GalleryDetailRow(
298314
modifier = Modifier.background(color = colorOddBg),
299315
name = R.string.gallery_info_field_sampler.asUiText(),
300316
value = state.sampler,
301317
color = colorOddText,
318+
onCopyTextClick = onCopyTextClick,
302319
)
303320
GalleryDetailRow(
304321
modifier = Modifier.background(color = colorEvenBg),
305322
name = R.string.gallery_info_field_seed.asUiText(),
306323
value = state.seed,
307324
color = colorEvenText,
325+
onCopyTextClick = onCopyTextClick,
308326
)
309327
GalleryDetailRow(
310328
modifier = Modifier.background(color = colorOddBg),
311329
name = R.string.gallery_info_field_sub_seed.asUiText(),
312330
value = state.subSeed,
313331
color = colorOddText,
332+
onCopyTextClick = onCopyTextClick,
314333
)
315334
GalleryDetailRow(
316335
modifier = Modifier.background(color = colorEvenBg),
317336
name = R.string.gallery_info_field_sub_seed_strength.asUiText(),
318337
value = state.subSeedStrength,
319338
color = colorEvenText,
339+
onCopyTextClick = onCopyTextClick,
320340
)
321341
if (state.generationType == AiGenerationResult.Type.IMAGE_TO_IMAGE) GalleryDetailRow(
322342
modifier = Modifier.background(color = colorOddBg),
323343
name = R.string.gallery_info_field_denoising_strength.asUiText(),
324344
value = state.denoisingStrength,
325345
color = colorOddText,
346+
onCopyTextClick = onCopyTextClick,
326347
)
327348
}
328349
},
329350
bottomBar = {
330351
Column(
331352
modifier = Modifier
332-
.background(color = MaterialTheme.colorScheme.background)
333-
.fillMaxWidth()
334-
.padding(horizontal = 16.dp)
335-
.padding(bottom = 16.dp, top = 2.dp),
353+
.background(color = MaterialTheme.colorScheme.background)
354+
.fillMaxWidth()
355+
.padding(horizontal = 16.dp)
356+
.padding(bottom = 16.dp, top = 2.dp),
336357
) {
337358
Row {
338359
OutlinedButton(
@@ -390,7 +411,9 @@ private fun GalleryDetailRow(
390411
name: UiText,
391412
value: UiText,
392413
color: Color,
414+
onCopyTextClick: (CharSequence) -> Unit = {},
393415
) {
416+
val rawValue = value.asString()
394417
Row(modifier) {
395418
GalleryDetailCell(
396419
text = name,
@@ -402,6 +425,18 @@ private fun GalleryDetailRow(
402425
modifier = Modifier.weight(column2Weight),
403426
color = color,
404427
)
428+
if (rawValue.isNotBlank()) {
429+
IconButton(
430+
onClick = { onCopyTextClick(rawValue) },
431+
) {
432+
Icon(
433+
modifier = Modifier.size(20.dp),
434+
imageVector = Icons.Default.ContentCopy,
435+
contentDescription = "Copy",
436+
tint = MaterialTheme.colorScheme.primary,
437+
)
438+
}
439+
}
405440
}
406441
}
407442

@@ -417,3 +452,15 @@ private fun GalleryDetailCell(
417452
color = color,
418453
)
419454
}
455+
456+
@Composable
457+
@Preview(showSystemUi = true, showBackground = true)
458+
private fun PreviewGalleryScreenTxt2ImgContentTabImage() {
459+
ScreenContent(state = mockGalleryDetailTxt2Img)
460+
}
461+
462+
@Composable
463+
@Preview(showSystemUi = true, showBackground = true)
464+
private fun PreviewGalleryScreenTxt2ImgContentTabInfo() {
465+
ScreenContent(state = mockGalleryDetailTxt2Img.copy(selectedTab = GalleryDetailState.Tab.INFO))
466+
}

0 commit comments

Comments
 (0)