Skip to content

Commit c322cf1

Browse files
committed
feat: Updated cliboard sync dialog
1 parent 9c99670 commit c322cf1

2 files changed

Lines changed: 103 additions & 46 deletions

File tree

app/src/main/java/com/sameerasw/airsync/presentation/ui/activities/ClipboardActionActivity.kt

Lines changed: 98 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,20 @@ import androidx.compose.animation.ExperimentalAnimationApi
1212
import androidx.compose.animation.fadeIn
1313
import androidx.compose.animation.fadeOut
1414
import androidx.compose.animation.togetherWith
15+
import androidx.compose.foundation.Image
1516
import androidx.compose.foundation.background
17+
import androidx.compose.foundation.border
1618
import androidx.compose.foundation.clickable
1719
import androidx.compose.foundation.layout.Box
1820
import androidx.compose.foundation.layout.Column
1921
import androidx.compose.foundation.layout.Spacer
2022
import androidx.compose.foundation.layout.fillMaxSize
23+
import androidx.compose.foundation.layout.fillMaxWidth
2124
import androidx.compose.foundation.layout.height
2225
import androidx.compose.foundation.layout.navigationBarsPadding
2326
import androidx.compose.foundation.layout.padding
2427
import androidx.compose.foundation.layout.size
28+
import androidx.compose.foundation.shape.CircleShape
2529
import androidx.compose.foundation.shape.RoundedCornerShape
2630
import androidx.compose.material.icons.Icons
2731
import androidx.compose.material.icons.rounded.CheckCircle
@@ -34,18 +38,27 @@ import androidx.compose.material3.Surface
3438
import androidx.compose.material3.Text
3539
import androidx.compose.runtime.Composable
3640
import androidx.compose.runtime.LaunchedEffect
41+
import androidx.compose.runtime.collectAsState
3742
import androidx.compose.runtime.getValue
3843
import androidx.compose.runtime.mutableStateOf
3944
import androidx.compose.runtime.remember
4045
import androidx.compose.runtime.setValue
4146
import androidx.compose.ui.Alignment
4247
import androidx.compose.ui.Modifier
48+
import androidx.compose.ui.draw.clip
49+
import androidx.compose.ui.layout.ContentScale
50+
import androidx.compose.ui.res.painterResource
51+
import androidx.compose.ui.res.stringResource
4352
import androidx.compose.ui.text.font.FontWeight
4453
import androidx.compose.ui.tooling.preview.Preview
4554
import androidx.compose.ui.unit.dp
55+
import com.sameerasw.airsync.R
56+
import com.sameerasw.airsync.data.local.DataStoreManager
57+
import com.sameerasw.airsync.domain.model.ConnectedDevice
4658
import com.sameerasw.airsync.ui.theme.AirSyncTheme
4759
import com.sameerasw.airsync.utils.ClipboardSyncManager
4860
import com.sameerasw.airsync.utils.ClipboardUtil
61+
import com.sameerasw.airsync.utils.DevicePreviewResolver
4962
import kotlinx.coroutines.delay
5063

5164
class ClipboardActionActivity : ComponentActivity() {
@@ -88,12 +101,19 @@ class ClipboardActionActivity : ComponentActivity() {
88101

89102
@Composable
90103
fun ClipboardActionScreen(hasWindowFocus: Boolean, onFinished: () -> Unit) {
104+
val context = androidx.compose.ui.platform.LocalContext.current
105+
val dataStoreManager = remember { DataStoreManager.getInstance(context) }
106+
val connectedDevice by dataStoreManager.getLastConnectedDevice().collectAsState(initial = null)
107+
91108
var uiState by remember { mutableStateOf<ClipboardUiState>(ClipboardUiState.Loading) }
92109
var hasAttemptedSync by remember { mutableStateOf(false) }
93110

94-
ClipboardActionScreenContent(uiState = uiState, onFinished = onFinished)
111+
ClipboardActionScreenContent(
112+
uiState = uiState,
113+
connectedDevice = connectedDevice,
114+
onFinished = onFinished
115+
)
95116

96-
val context = androidx.compose.ui.platform.LocalContext.current
97117
LaunchedEffect(hasWindowFocus) {
98118
if (hasWindowFocus && !hasAttemptedSync) {
99119
hasAttemptedSync = true
@@ -125,7 +145,11 @@ fun ClipboardActionScreen(hasWindowFocus: Boolean, onFinished: () -> Unit) {
125145

126146
@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterial3ExpressiveApi::class)
127147
@Composable
128-
fun ClipboardActionScreenContent(uiState: ClipboardUiState, onFinished: () -> Unit) {
148+
fun ClipboardActionScreenContent(
149+
uiState: ClipboardUiState,
150+
connectedDevice: ConnectedDevice?,
151+
onFinished: () -> Unit
152+
) {
129153
// Transparent background that dismisses on click
130154
Box(
131155
modifier = Modifier
@@ -145,7 +169,7 @@ fun ClipboardActionScreenContent(uiState: ClipboardUiState, onFinished: () -> Un
145169
) {
146170
Box(
147171
modifier = Modifier
148-
.padding(32.dp),
172+
.padding(24.dp),
149173
contentAlignment = Alignment.Center
150174
) {
151175
AnimatedContent(
@@ -156,47 +180,75 @@ fun ClipboardActionScreenContent(uiState: ClipboardUiState, onFinished: () -> Un
156180
Column(
157181
horizontalAlignment = Alignment.CenterHorizontally
158182
) {
159-
when (state) {
160-
is ClipboardUiState.Loading -> {
161-
LoadingIndicator(
162-
modifier = Modifier.size(48.dp),
163-
color = MaterialTheme.colorScheme.primary
164-
)
165-
Spacer(modifier = Modifier.height(16.dp))
166-
Text(
167-
text = "Syncing...",
168-
style = MaterialTheme.typography.titleMedium,
169-
fontWeight = FontWeight.Medium
170-
)
171-
}
172-
is ClipboardUiState.Success -> {
173-
Icon(
174-
imageVector = Icons.Rounded.CheckCircle,
175-
contentDescription = "Success",
176-
modifier = Modifier.size(48.dp)
177-
)
178-
Spacer(modifier = Modifier.height(16.dp))
179-
Text(
180-
text = "Clipboard Sent!",
181-
style = MaterialTheme.typography.titleMedium,
182-
fontWeight = FontWeight.Bold
183-
)
184-
}
185-
is ClipboardUiState.Error -> {
186-
Icon(
187-
imageVector = Icons.Rounded.Error,
188-
contentDescription = "Error",
189-
tint = MaterialTheme.colorScheme.error,
190-
modifier = Modifier.size(48.dp)
191-
)
192-
Spacer(modifier = Modifier.height(16.dp))
193-
Text(
194-
text = state.message,
195-
style = MaterialTheme.typography.titleMedium,
196-
color = MaterialTheme.colorScheme.error
197-
)
183+
// Device preview with overlay
184+
Box(
185+
contentAlignment = Alignment.Center,
186+
modifier = Modifier.padding(bottom = 16.dp)
187+
) {
188+
val previewRes = DevicePreviewResolver.getPreviewRes(connectedDevice)
189+
Image(
190+
painter = painterResource(id = previewRes),
191+
contentDescription = "Device Preview",
192+
modifier = Modifier.fillMaxWidth(0.9f),
193+
contentScale = ContentScale.Fit
194+
)
195+
196+
Box(
197+
modifier = Modifier
198+
.size(56.dp)
199+
.background(MaterialTheme.colorScheme.surfaceContainerHigh, shape = CircleShape)
200+
) {
201+
// Overlay icon/indicator
202+
when (state) {
203+
is ClipboardUiState.Loading -> {
204+
LoadingIndicator(
205+
modifier = Modifier.size(56.dp),
206+
color = MaterialTheme.colorScheme.primary
207+
)
208+
}
209+
210+
is ClipboardUiState.Success -> {
211+
Icon(
212+
imageVector = Icons.Rounded.CheckCircle,
213+
contentDescription = "Success",
214+
modifier = Modifier.size(56.dp),
215+
tint = MaterialTheme.colorScheme.primary
216+
)
217+
}
218+
219+
is ClipboardUiState.Error -> {
220+
Icon(
221+
imageVector = Icons.Rounded.Error,
222+
contentDescription = "Error",
223+
tint = MaterialTheme.colorScheme.error,
224+
modifier = Modifier.size(56.dp)
225+
)
226+
}
198227
}
199228
}
229+
}
230+
231+
Text(
232+
text = connectedDevice?.name ?: stringResource(R.string.your_mac),
233+
style = MaterialTheme.typography.titleMedium,
234+
color = MaterialTheme.colorScheme.onPrimary,
235+
modifier = Modifier
236+
.background(MaterialTheme.colorScheme.primary, shape = RoundedCornerShape(32.dp))
237+
.padding(horizontal = 16.dp, vertical = 4.dp),
238+
)
239+
240+
Spacer(modifier = Modifier.height(8.dp))
241+
242+
// Status Text
243+
Text(
244+
text = when (state) {
245+
is ClipboardUiState.Loading -> stringResource(R.string.sending)
246+
is ClipboardUiState.Success -> stringResource(R.string.clipboard_sent)
247+
is ClipboardUiState.Error -> stringResource(R.string.failed_to_send_clipboard)
248+
},
249+
style = MaterialTheme.typography.titleSmall,
250+
color = if (state is ClipboardUiState.Error) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.onSurface
251+
)
200252
}
201253
}
202254
}
@@ -214,22 +266,22 @@ sealed class ClipboardUiState {
214266
@Composable
215267
private fun ClipboardActionScreenPreviewLoading() {
216268
AirSyncTheme {
217-
ClipboardActionScreenContent(uiState = ClipboardUiState.Loading, onFinished = {})
269+
ClipboardActionScreenContent(uiState = ClipboardUiState.Loading, connectedDevice = null, onFinished = {})
218270
}
219271
}
220272

221273
@Preview(name = "Success State", showBackground = true)
222274
@Composable
223275
private fun ClipboardActionScreenPreviewSuccess() {
224276
AirSyncTheme {
225-
ClipboardActionScreenContent(uiState = ClipboardUiState.Success, onFinished = {})
277+
ClipboardActionScreenContent(uiState = ClipboardUiState.Success, connectedDevice = null, onFinished = {})
226278
}
227279
}
228280

229281
@Preview(name = "Error State", showBackground = true)
230282
@Composable
231283
private fun ClipboardActionScreenPreviewError() {
232284
AirSyncTheme {
233-
ClipboardActionScreenContent(uiState = ClipboardUiState.Error("Failed to sync"), onFinished = {})
285+
ClipboardActionScreenContent(uiState = ClipboardUiState.Error("Failed to sync"), connectedDevice = null, onFinished = {})
234286
}
235287
}

app/src/main/res/values/strings.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,9 @@
2121
<string name="sync_clipboard">Sync Clipboard</string>
2222
<string name="image_copied_to_clipboard">Image copied to clipboard</string>
2323
<string name="file_received_from_clipboard">File received from clipboard</string>
24+
<string name="sending">Sending Clipboard…</string>
25+
<string name="clipboard_sent">Clipboard Sent</string>
26+
<string name="failed_to_send_clipboard">Failed to Send Clipboard</string>
27+
<string name="your_mac">Your Mac</string>
28+
<string name="disconnected">Disconnected</string>
2429
</resources>

0 commit comments

Comments
 (0)