Skip to content

Commit

Permalink
Merge pull request #96 from Semper-Viventem/make-active-scanner-mode-…
Browse files Browse the repository at this point in the history
…expandable

Make active scanner mode expandable
  • Loading branch information
Semper-Viventem committed Jan 22, 2024
2 parents 3512638 + 3f141f1 commit 5e31a9a
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 57 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ android {

// This version code will be applied only for F-Droid builds, for other builds version code will be generated by gradle dynamically
// For some reason F-Droid requires version code to be hardcoded in the build.gradle file
versionCode = 1705859015
versionName = "0.22.2-beta"
versionCode = 1705859017
versionName = "0.22.3-beta"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down
154 changes: 102 additions & 52 deletions app/src/main/java/f/cking/software/ui/devicelist/DeviceListScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -192,53 +192,83 @@ object DeviceListScreen {
Row(verticalAlignment = Alignment.CenterVertically) {
Spacer(modifier = Modifier.width(16.dp))
RadarIcon()

val sortByDialog = rememberMaterialDialogState()
ThemedDialog(sortByDialog) {
Column(
Modifier
.fillMaxWidth()
.padding(vertical = 16.dp)
) {
Text(
modifier = Modifier.padding(16.dp),
text = stringResource(R.string.sort_by_title),
fontWeight = FontWeight.SemiBold,
fontSize = 20.sp
)
DeviceListViewModel.CurrentBatchSortingStrategy.entries.forEach { strategy ->
fun selectStrategy() {
viewModel.applyCurrentBatchSortingStrategy(strategy)
sortByDialog.hide()
}
Box(modifier = Modifier.clickable { selectStrategy() }) {
Row(
Modifier
.fillMaxWidth()
.padding(4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(checked = viewModel.currentBatchSortingStrategy == strategy, onCheckedChange = { selectStrategy() })
Spacer(modifier = Modifier.width(4.dp))
Text(text = stringResource(id = strategy.displayNameRes), color = MaterialTheme.colorScheme.onSurface)
}
}
}
}
}
Spacer(modifier = Modifier.width(8.dp))
Text(
text = stringResource(R.string.current_batch_title),
fontWeight = FontWeight.SemiBold,
fontSize = 20.sp,
)
Spacer(modifier = Modifier.weight(1f))
IconButton(onClick = { sortByDialog.show() }) {
Icon(
painter = painterResource(id = R.drawable.ic_sort),
contentDescription = stringResource(R.string.sort_by_title),
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.onSurface,
)
if (!viewModel.currentBatchViewState.isNullOrEmpty()) {
ExpandIcon(viewModel)
SortByIcon(viewModel)
}
}
Spacer(modifier = Modifier.height(8.dp))
CurrentBatchList(viewModel)
Spacer(modifier = Modifier.height(8.dp))
}
}

@Composable
private fun ExpandIcon(viewModel: DeviceListViewModel) {
val state = viewModel.activeScannerExpandedState
val icon = when (state) {
DeviceListViewModel.ActiveScannerExpandedState.COLLAPSED -> painterResource(id = R.drawable.ic_show_less)
DeviceListViewModel.ActiveScannerExpandedState.EXPANDED -> painterResource(id = R.drawable.ic_show_more)
}
IconButton(onClick = { viewModel.activeScannerExpandedState = state.next() }) {
Icon(
painter = icon,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurface,
)
}
}

@Composable
private fun SortByIcon(viewModel: DeviceListViewModel) {
val sortByDialog = rememberMaterialDialogState()
ThemedDialog(sortByDialog) {
Column(
Modifier
.fillMaxWidth()
.padding(vertical = 16.dp)
) {
Text(
modifier = Modifier.padding(16.dp),
text = stringResource(R.string.sort_by_title),
fontWeight = FontWeight.SemiBold,
fontSize = 20.sp
)
DeviceListViewModel.CurrentBatchSortingStrategy.entries.forEach { strategy ->
fun selectStrategy() {
viewModel.applyCurrentBatchSortingStrategy(strategy)
sortByDialog.hide()
}
Box(modifier = Modifier.clickable { selectStrategy() }) {
Row(
Modifier
.fillMaxWidth()
.padding(4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(checked = viewModel.currentBatchSortingStrategy == strategy, onCheckedChange = { selectStrategy() })
Spacer(modifier = Modifier.width(4.dp))
Text(text = stringResource(id = strategy.displayNameRes), color = MaterialTheme.colorScheme.onSurface)
}
}
}
}
}


IconButton(onClick = { sortByDialog.show() }) {
Icon(
painter = painterResource(id = R.drawable.ic_sort),
contentDescription = stringResource(R.string.sort_by_title),
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.onSurface,
)
}
}

Expand All @@ -253,13 +283,6 @@ object DeviceListScreen {
painter = if (atEnd) painter else animatedPainter,
contentDescription = null,
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = stringResource(R.string.current_batch_title),
fontWeight = FontWeight.SemiBold,
fontSize = 20.sp,
)
Spacer(modifier = Modifier.width(16.dp))
LaunchedEffect(key1 = radarIcon) {
while (isActive) {
delay(1200)
Expand All @@ -271,24 +294,51 @@ object DeviceListScreen {
@Composable
private fun CurrentBatchList(viewModel: DeviceListViewModel) {
val currentBatch = viewModel.currentBatchViewState!!
val mode = viewModel.activeScannerExpandedState
val visibleDevices = when (mode) {
DeviceListViewModel.ActiveScannerExpandedState.COLLAPSED -> currentBatch.take(DeviceListViewModel.ActiveScannerExpandedState.MAX_DEVICES_COUNT)
DeviceListViewModel.ActiveScannerExpandedState.EXPANDED -> currentBatch
}
if (currentBatch.isNotEmpty()) {
currentBatch.forEachIndexed { index, deviceData ->
visibleDevices.forEachIndexed { index, deviceData ->
DeviceListItem(
device = deviceData,
showSignalData = true,
showLastUpdate = false,
onClick = { viewModel.onDeviceClick(deviceData) },
onTagSelected = { viewModel.onTagSelected(it) },
)
if (index < currentBatch.lastIndex) {
if (index < visibleDevices.lastIndex) {
Divider()
}
}
if (mode == DeviceListViewModel.ActiveScannerExpandedState.COLLAPSED
&& visibleDevices.size < currentBatch.size
) {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
viewModel.activeScannerExpandedState = DeviceListViewModel.ActiveScannerExpandedState.EXPANDED
},
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = stringResource(R.string.active_mode_show_all, currentBatch.size.toString()),
modifier = Modifier.padding(16.dp),
color = MaterialTheme.colorScheme.onSurface,
fontWeight = FontWeight.SemiBold,
)
Icon(painter = painterResource(id = R.drawable.ic_more), contentDescription = null, tint = MaterialTheme.colorScheme.onSurface)
}
}
} else {
Text(
modifier = Modifier.padding(horizontal = 16.dp),
modifier = Modifier.padding(16.dp),
text = stringResource(R.string.current_batch_empty),
fontWeight = FontWeight.Light,
fontSize = 16.sp,
color = MaterialTheme.colorScheme.onSurface,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class DeviceListViewModel(

var currentBatchSortingStrategy by mutableStateOf(CurrentBatchSortingStrategy.GENERAL)
var devicesViewState by mutableStateOf(emptyList<DeviceData>())
var activeScannerExpandedState by mutableStateOf(ActiveScannerExpandedState.COLLAPSED)
var currentBatchViewState by mutableStateOf<List<DeviceData>?>(null)
var appliedFilter: List<FilterHolder> by mutableStateOf(emptyList())
var searchQuery: String? by mutableStateOf(null)
Expand Down Expand Up @@ -357,6 +358,18 @@ class DeviceListViewModel(
}, R.string.sort_type_by_distance)
}

enum class ActiveScannerExpandedState {
EXPANDED, COLLAPSED;

fun next(): ActiveScannerExpandedState {
return entries.elementAt((ordinal + 1) % entries.size)
}

companion object {
val MAX_DEVICES_COUNT = 3
}
}

companion object {
private const val PAGE_SIZE = 40
private const val INITIAL_PAGE = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ fun ClickableField(
fun DeviceListItem(
device: DeviceData,
showSignalData: Boolean = false,
showLastUpdate: Boolean = true,
onTagSelected: (tag: String) -> Unit = {},
onClick: () -> Unit,
) {
Expand Down Expand Up @@ -319,6 +320,19 @@ fun DeviceListItem(
fontWeight = FontWeight.Light,
)
Spacer(modifier = Modifier.height(4.dp))

val updateStr = if (showLastUpdate) {
stringResource(
R.string.lifetime_data_last_update,
device.firstDetectionPeriod(LocalContext.current),
device.lastDetectionPeriod(LocalContext.current),
)
} else {
stringResource(
R.string.lifetime_data,
device.firstDetectionPeriod(LocalContext.current),
)
}
Text(
text = stringResource(
R.string.lifetime_data,
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/ic_more.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M6,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
</vector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/ic_show_less.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M7.41,18.59L8.83,20 12,16.83 15.17,20l1.41,-1.41L12,14l-4.59,4.59zM16.59,5.41L15.17,4 12,7.17 8.83,4 7.41,5.41 12,10l4.59,-4.59z"/>
</vector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/ic_show_more.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,5.83L15.17,9l1.41,-1.41L12,3 7.41,7.59 8.83,9 12,5.83zM12,18.17L8.83,15l-1.41,1.41L12,21l4.59,-4.59L15.17,15 12,18.17z"/>
</vector>
3 changes: 2 additions & 1 deletion app/src/main/res/values-hu/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
<string name="last_location_update_time">Legutóbbi helyzet-frissítés: %s</string>
<string name="lat_template">szélesség: %s</string>
<string name="launch_on_system_startup_title">Indítás a rendszer indításával</string>
<string name="lifetime_data">örök: %1$s | legutóbbi frissítés: %2$s ideje</string>
<string name="lifetime_data">örök: %1$s</string>
<string name="lng_template">hosszúság: %s</string>
<string name="location_fetches_only_if_service_is_turned_on">A hely csak akkor jelenik meg, ha a szkenner elindul</string>
<string name="location_is_turned_off_subtitle">A Bluetooth radar nem tud szkennelni, ha a helyszolgáltatások ki vannak kapcsolva, az android korlátozásai miatt</string>
Expand Down Expand Up @@ -169,4 +169,5 @@
<string name="total_devices_around">%s összes eszköz a közelben</string>
<string name="turn_on">Bekapcsolás</string>
<string name="unknown_capital_case">ISMERETLEN</string>
<string name="lifetime_data_last_update">örök: %1$s | legutóbbi frissítés: %2$s ideje</string>
</resources>
3 changes: 2 additions & 1 deletion app/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@
<string name="device_details_month">Месяц</string>
<string name="device_details_all_time">Все время</string>
<string name="time_ago">%s назад</string>
<string name="lifetime_data">Время жизни: %1$s | Последнее обновление: %2$s назад</string>
<string name="lifetime_data">Время жизни: %1$s</string>
<string name="device_list_placeholder">Пока нет данных. Для начала сканирования нажмите на кнопку \"Сканировать\"</string>
<string name="tag_name">Имя тэга</string>
<string name="create_new_tag">Создать новый</string>
Expand Down Expand Up @@ -250,4 +250,5 @@
<string name="cannot_open_the_url">Не удаетс яоткрыть URL</string>
<string name="disclaimer">Внимание</string>
<string name="device_distance_disclaimer">Расстояние до устройства считается на основе RSSI и является приблизительным</string>
<string name="lifetime_data_last_update">Время жизни: %1$s | Последнее обновление: %2$s назад</string>
</resources>
4 changes: 3 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@
<string name="device_details_month">Month</string>
<string name="device_details_all_time">All time</string>
<string name="time_ago">%s ago</string>
<string name="lifetime_data">lifetime: %1$s | last update: %2$s ago</string>
<string name="lifetime_data_last_update">lifetime: %1$s | last update: %2$s ago</string>
<string name="lifetime_data">lifetime: %1$s</string>
<string name="device_list_placeholder">No data yet. To start scanning, click on the Scan button</string>
<string name="tag_name">Tag name</string>
<string name="create_new_tag">Create new</string>
Expand All @@ -207,6 +208,7 @@
<string name="sort_by_title">Sort by</string>
<string name="sort_type_standart">Default</string>
<string name="sort_type_by_distance">Distance</string>
<string name="active_mode_show_all">Show all %s online devices</string>

<!-- Main Screen -->
<string name="menu_device_list">Device list</string>
Expand Down

0 comments on commit 5e31a9a

Please sign in to comment.