Skip to content

Commit 19364fb

Browse files
committed
Refactor DiffCheckerScreen and introduce DiffViewerScreen
This commit refactors the `DiffCheckerScreen` to use `DiffCheckerViewModel` for state management and introduces a new `DiffViewerScreen` for displaying diff results in a separate view. **Key Changes:** - **DiffCheckerScreen (`DiffCheckerScreen.kt`):** - State variables (`oldText`, `newText`, `realTimeDiff`, `expanded`, `selectedViewType`) are now managed by `DiffCheckerViewModel` using `StateFlow`. - UI interactions (updating text, toggling real-time diff, expanding menu, selecting view type, swapping texts) now call corresponding methods in the ViewModel. - Added a FloatingActionButton (FAB) with an "OpenInFull" icon that appears when diff results are available, allowing navigation to `DiffViewerScreen`. - Renamed `ColumCharDiffText` to `SeparateCharDiffText` for clarity. - **DiffViewerScreen (`DiffViewerScreen.kt`):** - New screen to display the diff results in a dedicated view. - Uses `DiffCheckerViewModel` to access `diffResult`, `selectedViewType`, and `expanded` state. - Provides a TopAppBar with a back button and a menu to switch between diff view types (Two Side, Separate, Unified), similar to `DiffCheckerScreen`. - Displays the diff result using `TwoSideCharDiffText`, `SeparateCharDiffText`, or `UnifiedCharDiffText` based on the selected view type. - **DiffCheckerViewModel (`DiffCheckerViewModel.kt`):** - Added `StateFlow`s for `oldText`, `newText`, `realTimeDiff`, `expanded`, and `selectedViewType`. - Added methods to update these states (`updateOldText`, `updateNewText`, `setRealTimeDiff`, `setExpanded`, `selectViewType`, `swapTexts`). - Added `navigateToDiffViewer()` and `goBack()` methods for navigation. - When `realTimeDiff` is enabled, `calculateDiff` is automatically called on text changes or swaps. - **Navigation (`MainActivity.kt`):** - `DiffCheckerViewModel` is now instantiated lazily and shared between `DiffCheckerScreen` and `DiffViewerScreen`. - Added `DiffViewerScreen` to the `NavHost`. - **UI Components:** - Renamed `ColumCharDiffText.kt` to `SeparateCharDiffText.kt` and updated its usage. - `SeparateCharDiffText.kt`: Minor layout adjustment for "Original Text" / "-count" and "Changed Text" / "+count" to be in a `Row`. - `UnifiedCharDiffText.kt`: Changed title from "Unified Diff" to "Unified View".
1 parent 2710fb1 commit 19364fb

File tree

6 files changed

+318
-99
lines changed

6 files changed

+318
-99
lines changed

app/src/main/java/dev/jahidhasanco/diffly/presentation/MainActivity.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,19 @@ class MainActivity : ComponentActivity() {
4242
fun AppNavHost() {
4343
val navController = rememberNavController()
4444
val router = NavControllerRouter(navController)
45-
45+
val diffCheckerViewModel by lazy {
46+
DiffCheckerViewModel(AppModule.calculateDiffUseCase, router)
47+
}
4648
NavHost(
4749
navController = navController,
4850
startDestination = Screen.DiffChecker.route
4951
) {
5052
composable(Screen.DiffChecker.route) {
51-
val viewModel by lazy {
52-
DiffCheckerViewModel(AppModule.calculateDiffUseCase, router)
53-
}
54-
DiffCheckerScreen(viewModel)
53+
54+
DiffCheckerScreen(diffCheckerViewModel)
5555
}
5656
composable(Screen.DiffViewer.route) {
57-
DiffViewerScreen()
57+
DiffViewerScreen(diffCheckerViewModel)
5858
}
5959
}
6060
}

app/src/main/java/dev/jahidhasanco/diffly/presentation/component/ColumCharDiffText.kt renamed to app/src/main/java/dev/jahidhasanco/diffly/presentation/component/SeparateCharDiffText.kt

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package dev.jahidhasanco.diffly.presentation.component
33
import androidx.compose.foundation.background
44
import androidx.compose.foundation.layout.Box
55
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.Row
67
import androidx.compose.foundation.layout.Spacer
78
import androidx.compose.foundation.layout.fillMaxSize
89
import androidx.compose.foundation.layout.fillMaxWidth
@@ -24,25 +25,28 @@ import dev.jahidhasanco.diffly.presentation.theme.added
2425
import dev.jahidhasanco.diffly.presentation.theme.delete
2526

2627
@Composable
27-
fun ColumCharDiffText(diffResult: List<DiffEntry>) {
28+
fun SeparateCharDiffText(diffResult: List<DiffEntry>) {
2829
Column(modifier = Modifier.fillMaxSize()) {
2930

3031
// Original Text Column
31-
Text(
32-
"Original Text",
33-
modifier = Modifier.padding(8.dp),
34-
style = MaterialTheme.typography.titleMedium
35-
)
36-
val deletedCount = diffResult.count { it.type == DiffType.CHANGED || it.type == DiffType.DELETED }
37-
if (deletedCount > 0) {
32+
Row {
3833
Text(
39-
"-$deletedCount",
40-
modifier = Modifier.padding(start = 8.dp, bottom = 8.dp),
41-
style = MaterialTheme.typography.bodyMedium.copy(
42-
color = delete,
43-
fontWeight = MaterialTheme.typography.titleMedium.fontWeight
44-
)
34+
"Original Text",
35+
modifier = Modifier.padding(8.dp),
36+
style = MaterialTheme.typography.titleMedium
4537
)
38+
val deletedCount =
39+
diffResult.count { it.type == DiffType.CHANGED || it.type == DiffType.DELETED }
40+
if (deletedCount > 0) {
41+
Text(
42+
"-$deletedCount",
43+
modifier = Modifier.padding(8.dp),
44+
style = MaterialTheme.typography.bodyMedium.copy(
45+
color = delete,
46+
fontWeight = MaterialTheme.typography.titleMedium.fontWeight
47+
)
48+
)
49+
}
4650
}
4751

4852
LazyColumn(
@@ -56,7 +60,10 @@ fun ColumCharDiffText(diffResult: List<DiffEntry>) {
5660
entry.charDiffs?.filter { it.type != CharDiffType.INSERTED }
5761
}
5862
val color = when (entry.type) {
59-
DiffType.ADDED, DiffType.DELETED, DiffType.CHANGED -> delete.copy(alpha = 0.3f)
63+
DiffType.ADDED, DiffType.DELETED, DiffType.CHANGED -> delete.copy(
64+
alpha = 0.3f
65+
)
66+
6067
else -> Color.Unspecified
6168
}
6269

@@ -76,25 +83,25 @@ fun ColumCharDiffText(diffResult: List<DiffEntry>) {
7683
}
7784
}
7885

79-
// Spacer between sections
8086
Spacer(modifier = Modifier.height(8.dp))
81-
82-
// Changed Text Column
83-
Text(
84-
"Changed Text",
85-
modifier = Modifier.padding(8.dp),
86-
style = MaterialTheme.typography.titleMedium
87-
)
88-
val addedCount = diffResult.count { it.type == DiffType.CHANGED || it.type == DiffType.ADDED }
89-
if (addedCount > 0) {
87+
Row {
9088
Text(
91-
"+$addedCount",
92-
modifier = Modifier.padding(start = 8.dp, bottom = 8.dp),
93-
style = MaterialTheme.typography.bodyMedium.copy(
94-
color = added,
95-
fontWeight = MaterialTheme.typography.titleMedium.fontWeight
96-
)
89+
"Changed Text",
90+
modifier = Modifier.padding(8.dp),
91+
style = MaterialTheme.typography.titleMedium
9792
)
93+
val addedCount =
94+
diffResult.count { it.type == DiffType.CHANGED || it.type == DiffType.ADDED }
95+
if (addedCount > 0) {
96+
Text(
97+
"+$addedCount",
98+
modifier = Modifier.padding(8.dp),
99+
style = MaterialTheme.typography.bodyMedium.copy(
100+
color = added,
101+
fontWeight = MaterialTheme.typography.titleMedium.fontWeight
102+
)
103+
)
104+
}
98105
}
99106

100107
LazyColumn(
@@ -108,7 +115,10 @@ fun ColumCharDiffText(diffResult: List<DiffEntry>) {
108115
entry.charDiffs?.filter { it.type != CharDiffType.DELETED }
109116
}
110117
val color = when (entry.type) {
111-
DiffType.ADDED, DiffType.DELETED, DiffType.CHANGED -> added.copy(alpha = 0.3f)
118+
DiffType.ADDED, DiffType.DELETED, DiffType.CHANGED -> added.copy(
119+
alpha = 0.3f
120+
)
121+
112122
else -> Color.Unspecified
113123
}
114124

app/src/main/java/dev/jahidhasanco/diffly/presentation/component/UnifiedCharDiffText.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fun UnifiedCharDiffText(diffResult: List<DiffEntry>) {
3131
) {
3232
item {
3333
Text(
34-
"Unified Diff",
34+
"Unified View",
3535
modifier = Modifier.padding(8.dp),
3636
style = MaterialTheme.typography.titleMedium
3737
)

app/src/main/java/dev/jahidhasanco/diffly/presentation/screen/DiffCheckerScreen.kt

Lines changed: 57 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
1818
import androidx.compose.material.icons.Icons
1919
import androidx.compose.material.icons.filled.Check
2020
import androidx.compose.material.icons.filled.MoreVert
21+
import androidx.compose.material.icons.filled.OpenInFull
2122
import androidx.compose.material.icons.filled.SwapVert
2223
import androidx.compose.material3.Button
2324
import androidx.compose.material3.ButtonDefaults
@@ -39,17 +40,14 @@ import androidx.compose.material3.TopAppBarDefaults
3940
import androidx.compose.runtime.Composable
4041
import androidx.compose.runtime.collectAsState
4142
import androidx.compose.runtime.getValue
42-
import androidx.compose.runtime.mutableStateOf
43-
import androidx.compose.runtime.remember
44-
import androidx.compose.runtime.setValue
4543
import androidx.compose.ui.Alignment
4644
import androidx.compose.ui.Modifier
4745
import androidx.compose.ui.draw.scale
4846
import androidx.compose.ui.graphics.Color
4947
import androidx.compose.ui.text.font.FontWeight
5048
import androidx.compose.ui.unit.dp
5149
import dev.jahidhasanco.diffly.domain.model.DiffViewType
52-
import dev.jahidhasanco.diffly.presentation.component.ColumCharDiffText
50+
import dev.jahidhasanco.diffly.presentation.component.SeparateCharDiffText
5351
import dev.jahidhasanco.diffly.presentation.component.TwoSideCharDiffText
5452
import dev.jahidhasanco.diffly.presentation.component.UnifiedCharDiffText
5553
import dev.jahidhasanco.diffly.presentation.theme.background
@@ -59,14 +57,16 @@ import dev.jahidhasanco.diffly.presentation.viewmodel.DiffCheckerViewModel
5957
@OptIn(ExperimentalMaterial3Api::class)
6058
@Composable
6159
fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
62-
var oldText by remember { mutableStateOf("") }
63-
var newText by remember { mutableStateOf("") }
60+
val oldText by viewModel.oldText.collectAsState()
61+
val newText by viewModel.newText.collectAsState()
62+
val realTimeDiff by viewModel.realTimeDiff.collectAsState()
63+
val expanded by viewModel.expanded.collectAsState()
64+
val selectedViewType by viewModel.selectedViewType.collectAsState()
6465
val diffResult by viewModel.diffResult.collectAsState()
65-
var realTimeDiff by remember { mutableStateOf(false) }
66-
var expanded by remember { mutableStateOf(false) }
67-
var selectedViewType by remember { mutableStateOf(DiffViewType.TWO_SIDE) }
6866
Scaffold(
69-
modifier = Modifier.fillMaxSize().imePadding(),
67+
modifier = Modifier
68+
.fillMaxSize()
69+
.imePadding(),
7070
containerColor = background,
7171
topBar = {
7272
TopAppBar(
@@ -94,15 +94,9 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
9494
modifier = Modifier.padding(end = 2.dp)
9595
)
9696
Switch(
97-
modifier = Modifier
98-
.scale(0.7f),
97+
modifier = Modifier.scale(0.7f),
9998
checked = realTimeDiff,
100-
onCheckedChange = {
101-
realTimeDiff = it
102-
if (it) {
103-
viewModel.calculateDiff(oldText, newText)
104-
}
105-
},
99+
onCheckedChange = viewModel::setRealTimeDiff,
106100
colors = SwitchDefaults.colors(
107101
checkedThumbColor = primary,
108102
uncheckedThumbColor = Color.Gray,
@@ -113,7 +107,7 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
113107
}
114108

115109
Box {
116-
IconButton(onClick = { expanded = true }) {
110+
IconButton(onClick = { viewModel.setExpanded(!expanded) }) {
117111
Icon(
118112
Icons.Default.MoreVert,
119113
contentDescription = "Menu"
@@ -122,7 +116,7 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
122116

123117
DropdownMenu(
124118
expanded = expanded,
125-
onDismissRequest = { expanded = false }) {
119+
onDismissRequest = { viewModel.setExpanded(false) }) {
126120
DropdownMenuItem(
127121
text = { Text("Two Side View") },
128122
trailingIcon = when (selectedViewType) {
@@ -138,8 +132,9 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
138132
else -> null
139133
},
140134
onClick = {
141-
selectedViewType = DiffViewType.TWO_SIDE
142-
expanded = false
135+
viewModel.selectViewType(
136+
DiffViewType.TWO_SIDE
137+
)
143138
})
144139
DropdownMenuItem(
145140
text = { Text("Separate View") },
@@ -156,8 +151,9 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
156151
else -> null
157152
},
158153
onClick = {
159-
selectedViewType = DiffViewType.SEPARATE
160-
expanded = false
154+
viewModel.selectViewType(
155+
DiffViewType.SEPARATE
156+
)
161157
})
162158
DropdownMenuItem(
163159
text = { Text("Unified View") },
@@ -174,13 +170,32 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
174170
else -> null
175171
},
176172
onClick = {
177-
selectedViewType = DiffViewType.UNIFIED
178-
expanded = false
173+
viewModel.selectViewType(
174+
DiffViewType.UNIFIED
175+
)
179176
})
180177
}
181178
}
182179
})
183-
}) { innerPadding ->
180+
}, floatingActionButton = {
181+
if (diffResult.isNotEmpty()) {
182+
IconButton(
183+
onClick = viewModel::navigateToDiffViewer,
184+
colors = IconButtonDefaults.iconButtonColors(
185+
containerColor = primary,
186+
contentColor = Color.White
187+
)
188+
) {
189+
Icon(
190+
imageVector = Icons.Default.OpenInFull,
191+
contentDescription = "Expand",
192+
tint = Color.White
193+
)
194+
}
195+
}
196+
}
197+
198+
) { innerPadding ->
184199
Column(
185200
modifier = Modifier
186201
.padding(innerPadding)
@@ -189,12 +204,7 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
189204
) {
190205
OutlinedTextField(
191206
value = oldText,
192-
onValueChange = {
193-
oldText = it
194-
if (realTimeDiff) {
195-
viewModel.calculateDiff(oldText, newText)
196-
}
197-
},
207+
onValueChange = viewModel::updateOldText,
198208
label = {
199209
Text(
200210
"Original Text",
@@ -221,24 +231,13 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
221231
singleLine = false
222232
)
223233

224-
225234
Spacer(modifier = Modifier.height(4.dp))
226-
227-
// swap icon button
228235
IconButton(
229-
onClick = {
230-
val temp = oldText
231-
oldText = newText
232-
newText = temp
233-
if (realTimeDiff) {
234-
viewModel.calculateDiff(oldText, newText)
235-
}
236-
},
236+
onClick = viewModel::swapTexts,
237237
colors = IconButtonDefaults.iconButtonColors(
238238
containerColor = Color.Transparent, contentColor = primary
239239
),
240-
modifier = Modifier
241-
.align(Alignment.CenterHorizontally)
240+
modifier = Modifier.align(Alignment.CenterHorizontally)
242241
) {
243242
Icon(
244243
imageVector = Icons.Default.SwapVert,
@@ -251,21 +250,20 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
251250
}
252251
Spacer(modifier = Modifier.height(4.dp))
253252
OutlinedTextField(
254-
value = newText, onValueChange = {
255-
newText = it
256-
if (realTimeDiff) {
257-
viewModel.calculateDiff(oldText, newText)
258-
}
259-
}, modifier = Modifier
253+
value = newText,
254+
onValueChange = viewModel::updateNewText,
255+
modifier = Modifier
260256
.fillMaxWidth()
261257
.height(150.dp),
262258

263-
shape = RoundedCornerShape(8.dp), label = {
259+
shape = RoundedCornerShape(8.dp),
260+
label = {
264261
Text(
265262
"Changed Text",
266263
style = MaterialTheme.typography.titleSmall
267264
)
268-
}, colors = TextFieldDefaults.colors(
265+
},
266+
colors = TextFieldDefaults.colors(
269267
focusedIndicatorColor = primary,
270268
unfocusedIndicatorColor = Color.White,
271269
focusedContainerColor = Color.White,
@@ -276,7 +274,8 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
276274
unfocusedTextColor = Color.Black
277275
),
278276

279-
maxLines = Int.MAX_VALUE, singleLine = false
277+
maxLines = Int.MAX_VALUE,
278+
singleLine = false
280279
)
281280

282281
Spacer(modifier = Modifier.height(16.dp))
@@ -301,17 +300,16 @@ fun DiffCheckerScreen(viewModel: DiffCheckerViewModel) {
301300
Text("Find Difference")
302301
}
303302

304-
Box (
303+
Box(
305304
modifier = Modifier
306305
.fillMaxWidth()
307306
.weight(1f)
308307
.padding(8.dp)
309308
.background(Color.White, RoundedCornerShape(8.dp))
310-
)
311-
{
309+
) {
312310
when (selectedViewType) {
313311
DiffViewType.TWO_SIDE -> TwoSideCharDiffText(diffResult)
314-
DiffViewType.SEPARATE -> ColumCharDiffText(diffResult)
312+
DiffViewType.SEPARATE -> SeparateCharDiffText(diffResult)
315313
DiffViewType.UNIFIED -> UnifiedCharDiffText(diffResult)
316314
}
317315
}

0 commit comments

Comments
 (0)