-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
612 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package components | ||
|
||
import androidx.compose.foundation.* | ||
import androidx.compose.foundation.layout.* | ||
import androidx.compose.foundation.lazy.LazyColumn | ||
import androidx.compose.foundation.lazy.rememberLazyListState | ||
import androidx.compose.material3.MaterialTheme | ||
import androidx.compose.runtime.* | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.geometry.Offset | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.text.TextStyle | ||
import androidx.compose.ui.text.drawText | ||
import androidx.compose.ui.text.rememberTextMeasurer | ||
import androidx.compose.ui.text.style.TextAlign | ||
import androidx.compose.ui.text.style.TextOverflow | ||
import androidx.compose.ui.unit.Constraints | ||
import androidx.compose.ui.unit.dp | ||
import theme.ColorBox | ||
import theme.Fonts | ||
|
||
@Composable | ||
fun TableView( | ||
tableRows: List<TableItemRow>, | ||
columnCount : Int, | ||
modifier: Modifier, | ||
itemContent: @Composable (column: Int,row : Int) -> String | ||
) { | ||
|
||
val scrollState = rememberLazyListState() | ||
|
||
Column(modifier = modifier) { | ||
TableItem( | ||
modifier = Modifier.fillMaxWidth().height(64.dp).background(ColorBox.primary.copy(0.2f)).padding(start = 20.dp, end = 20.dp), | ||
textStyle = MaterialTheme.typography.labelSmall.copy(fontFamily = Fonts.open_sans), | ||
textColor = ColorBox.text, | ||
list = tableRows.map { Triple(it.title,it.weight,it.textAlign) } | ||
) | ||
Box(Modifier.fillMaxWidth()) { | ||
LazyColumn(Modifier.fillMaxWidth(), state = scrollState) { | ||
items(columnCount) { column -> | ||
val bg = if (column % 2 == 0) ColorBox.text.copy(0.03f) else Color.Transparent | ||
TableItem( | ||
modifier = Modifier.fillMaxWidth().height(58.dp).background(bg).padding(start = 20.dp, end = 20.dp), | ||
textStyle = MaterialTheme.typography.bodyMedium.copy(fontFamily = Fonts.open_sans), | ||
textColor = ColorBox.text, | ||
list = tableRows.mapIndexed { index, tableItemRow -> Triple(itemContent(column,index),tableItemRow.weight,tableItemRow.textAlign) } | ||
) | ||
} | ||
} | ||
if (scrollState.canScrollForward || scrollState.canScrollBackward) { | ||
VerticalScrollbar( | ||
modifier = Modifier.align(Alignment.CenterEnd), | ||
style = LocalScrollbarStyle.current | ||
.copy(thickness = 5.dp, hoverColor = ColorBox.text.copy(0.6f), unhoverColor = ColorBox.text.copy(0.1f)), | ||
adapter = rememberScrollbarAdapter(scrollState) | ||
) | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
data class TableItemRow ( | ||
var weight : Float, | ||
var title : String, | ||
var textAlign: TextAlign | ||
) | ||
|
||
@Composable | ||
private fun TableItem (modifier: Modifier,textColor: Color,textStyle : TextStyle,list: List<Triple<String,Float,TextAlign>>) { | ||
val weights = remember { mutableStateListOf<Float>() } | ||
var totalWeight by remember { mutableStateOf(0f) } | ||
val textMeasurer = rememberTextMeasurer() | ||
LaunchedEffect(list) { | ||
weights.clear() | ||
totalWeight = 0f | ||
weights.addAll(list.map { | ||
totalWeight += it.second | ||
it.second | ||
}) | ||
} | ||
Canvas(modifier) { | ||
if (weights.isNotEmpty()) { | ||
var currentX = 0f | ||
for (i in list.indices) { | ||
val childWidth = (size.width * (weights[i] / totalWeight)) | ||
val textLayoutResult = textMeasurer.measure( | ||
text = list[i].first, | ||
style = textStyle.copy(textAlign = list[i].third), | ||
maxLines = 2, | ||
softWrap = true, | ||
overflow = TextOverflow.Clip, | ||
constraints = Constraints(0,childWidth.toInt(),0,size.height.toInt()) | ||
) | ||
drawText( | ||
textLayoutResult = textLayoutResult, | ||
topLeft = Offset(currentX,size.height / 2 - textLayoutResult.size.height / 2), | ||
color = textColor | ||
) | ||
currentX += childWidth | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package core | ||
|
||
import java.io.File | ||
import java.nio.file.Paths | ||
import java.sql.Connection | ||
import java.sql.DriverManager | ||
import java.util.* | ||
|
||
object Database { | ||
|
||
private const val APP_NAME: String = "librespeed-desktop" | ||
private fun getDatabasePath(): String { | ||
val osName = System.getProperty("os.name").lowercase(Locale.getDefault()) | ||
return if (osName.contains("linux")) { | ||
Paths.get(System.getProperty("user.home"), ".local", "share", APP_NAME).toString() | ||
} else if (osName.contains("windows")) { | ||
System.getProperty("user.home") + File.separator + "AppData" + File.separator + "Roaming" + File.separator + APP_NAME | ||
} else if (osName.contains("mac")) { | ||
Paths.get(System.getProperty("user.home"), "Library", "Application Support", APP_NAME).toString() | ||
} else { | ||
throw UnsupportedOperationException("Unsupported operating system") | ||
} | ||
} | ||
|
||
private lateinit var connection: Connection | ||
fun initDB() { | ||
File(getDatabasePath()).mkdirs() | ||
val dbFile = File(getDatabasePath(), "librespeed.db") | ||
Class.forName("org.sqlite.JDBC") | ||
connection = DriverManager.getConnection("jdbc:sqlite:$dbFile") | ||
createTables() | ||
} | ||
|
||
private fun createTables() { | ||
val statement = connection.createStatement() | ||
try { | ||
statement.executeUpdate( | ||
"CREATE TABLE IF NOT EXISTS history (" + | ||
"id INTEGER PRIMARY KEY AUTOINCREMENT," + | ||
"netAdapter TEXT," + | ||
"ping REAL," + | ||
"jitter REAL," + | ||
"download REAL," + | ||
"upload REAL," + | ||
"ispInfo TEXT," + | ||
"testPoint TEXT," + | ||
"date INTEGER" + | ||
")" | ||
) | ||
} catch (_: Exception) { | ||
} finally { | ||
statement.close() | ||
} | ||
} | ||
fun saveHistory(model: ModelHistory) { | ||
val statement = connection.prepareStatement("INSERT INTO history (netAdapter,ping,jitter,download,upload,ispInfo,testPoint,date) VALUES (?,?,?,?,?,?,?,?)") | ||
try { | ||
statement.setString(1, model.netAdapter) | ||
statement.setDouble(2, model.ping) | ||
statement.setDouble(3, model.jitter) | ||
statement.setDouble(4, model.download) | ||
statement.setDouble(5, model.upload) | ||
statement.setString(6, model.ispInfo) | ||
statement.setString(7, model.testPoint) | ||
statement.setLong(8, model.date) | ||
statement.executeUpdate() | ||
} catch (_ : Exception) {} finally { | ||
statement.close() | ||
} | ||
} | ||
fun readHistory() : MutableList<ModelHistory> { | ||
val statement = connection.prepareStatement("SELECT * FROM history ORDER BY id DESC") | ||
val resultSet = statement.executeQuery() | ||
val result = mutableListOf<ModelHistory>() | ||
while (resultSet.next()) { | ||
result.add( | ||
ModelHistory( | ||
id = resultSet.getInt("id"), | ||
netAdapter = resultSet.getString("netAdapter"), | ||
ping = resultSet.getDouble("ping"), | ||
jitter = resultSet.getDouble("jitter"), | ||
download = resultSet.getDouble("download"), | ||
upload = resultSet.getDouble("upload"), | ||
ispInfo = resultSet.getString("ispInfo"), | ||
testPoint = resultSet.getString("testPoint"), | ||
date = resultSet.getLong("date")) | ||
) | ||
} | ||
return result | ||
} | ||
fun clearHistory() { | ||
val statement = connection.createStatement() | ||
try { | ||
statement.executeUpdate("DELETE FROM history") | ||
} catch (_ : Exception) {} finally { | ||
statement.close() | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package core | ||
|
||
data class ModelHistory( | ||
var id : Int = 0, | ||
var netAdapter : String, | ||
var ping : Double, | ||
var jitter : Double, | ||
var download : Double, | ||
var upload : Double, | ||
var ispInfo : String, | ||
var testPoint : String, | ||
var date : Long | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,6 @@ object Route { | |
|
||
const val SPLASH = "splash" | ||
const val HOME = "home" | ||
const val HISTORY = "history" | ||
|
||
} |
Oops, something went wrong.