Skip to content

Commit 8db43ee

Browse files
committed
Disconnect Button
1 parent 683ab74 commit 8db43ee

File tree

6 files changed

+110
-38
lines changed

6 files changed

+110
-38
lines changed

app/src/main/java/dev/musakavak/uzayan/MainActivity.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import dev.musakavak.uzayan.components.RemoteCommandsCard
3434
import dev.musakavak.uzayan.components.ScreenCastLauncher
3535
import dev.musakavak.uzayan.managers.AllowListManager
3636
import dev.musakavak.uzayan.services.UzayanForegroundService
37+
import dev.musakavak.uzayan.socket.ConnectionState
3738
import dev.musakavak.uzayan.ui.theme.UzayanTheme
3839
import kotlinx.coroutines.launch
3940

@@ -91,6 +92,7 @@ class MainActivity : ComponentActivity() {
9192
ConnectionStateCard(
9293
padding,
9394
::startService,
95+
::closeConnection,
9496
::startServiceFromUri,
9597
setSheetContent
9698
)
@@ -131,5 +133,10 @@ class MainActivity : ComponentActivity() {
131133
startForegroundService(intent)
132134
}
133135
}
136+
137+
private fun closeConnection(){
138+
stopService(Intent(this, UzayanForegroundService::class.java))
139+
ConnectionState.setDefault()
140+
}
134141
}
135142

app/src/main/java/dev/musakavak/uzayan/components/ConnectionStateCard.kt

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,33 @@ import androidx.compose.foundation.layout.Row
77
import androidx.compose.foundation.layout.fillMaxHeight
88
import androidx.compose.foundation.layout.fillMaxWidth
99
import androidx.compose.foundation.layout.padding
10+
import androidx.compose.foundation.lazy.LazyRow
11+
import androidx.compose.material.icons.Icons
12+
import androidx.compose.material.icons.filled.Close
1013
import androidx.compose.material3.AssistChip
14+
import androidx.compose.material3.AssistChipDefaults
1115
import androidx.compose.material3.Card
1216
import androidx.compose.material3.CircularProgressIndicator
17+
import androidx.compose.material3.ElevatedAssistChip
1318
import androidx.compose.material3.Icon
1419
import androidx.compose.material3.MaterialTheme
20+
import androidx.compose.material3.OutlinedButton
1521
import androidx.compose.material3.Text
1622
import androidx.compose.runtime.Composable
1723
import androidx.compose.ui.Alignment
1824
import androidx.compose.ui.Modifier
1925
import androidx.compose.ui.res.painterResource
2026
import androidx.compose.ui.res.stringResource
2127
import androidx.compose.ui.unit.Dp
28+
import androidx.compose.ui.unit.dp
2229
import dev.musakavak.uzayan.R
2330
import dev.musakavak.uzayan.socket.ConnectionState
2431

2532
@Composable
2633
fun ConnectionStateCard(
2734
padding: Dp,
2835
startService: (String?, Int?, Int?, Boolean?) -> Unit,
36+
closeConnection: () -> Unit,
2937
startServiceFromUri: (Uri) -> Unit,
3038
setSheetContent: (String) -> Unit
3139
) {
@@ -41,28 +49,32 @@ fun ConnectionStateCard(
4149
) {
4250
when (ConnectionState.currentStatus) {
4351
200 -> ManualPairCard(startService, startServiceFromUri)
44-
201 -> ConnectingStatus(padding)
45-
202 -> ConnectedDeviceCard(padding, setSheetContent)
52+
201 -> ConnectingStatus(padding,closeConnection)
53+
202 -> ConnectedDeviceCard(padding, setSheetContent,closeConnection)
4654
}
4755
}
4856
}
4957
}
5058

5159
@Composable
52-
fun ConnectingStatus(padding: Dp) {
60+
fun ConnectingStatus(padding: Dp,closeConnection:()->Unit) {
5361
Row(
62+
modifier = Modifier.fillMaxWidth(),
5463
verticalAlignment = Alignment.CenterVertically,
5564
horizontalArrangement = Arrangement.SpaceBetween
5665
) {
5766
ConnectionState.connectingStatus?.let {
5867
CircularProgressIndicator(modifier = Modifier.padding(end = padding))
5968
Text(text = stringResource(id = it), style = MaterialTheme.typography.headlineLarge)
69+
OutlinedButton(onClick = closeConnection) {
70+
Text(text = stringResource(id = R.string.cancel))
71+
}
6072
}
6173
}
6274
}
6375

6476
@Composable
65-
fun ConnectedDeviceCard(padding: Dp, setSheetContent: (String) -> Unit) {
77+
fun ConnectedDeviceCard(padding: Dp, setSheetContent: (String) -> Unit,closeConnection: () -> Unit) {
6678
Column(modifier = Modifier.fillMaxHeight()) {
6779
Row(
6880
modifier = Modifier.fillMaxWidth(),
@@ -90,29 +102,56 @@ fun ConnectedDeviceCard(padding: Dp, setSheetContent: (String) -> Unit) {
90102
)
91103
}
92104
}
93-
Row(modifier = Modifier.fillMaxWidth()) {
94-
AssistChip(onClick = { setSheetContent("commands") },
95-
leadingIcon = {
96-
Icon(
97-
painter = painterResource(R.drawable.terminal),
98-
contentDescription = stringResource(R.string.remote_commands)
99-
)
100-
},
101-
label = {
102-
Text(text = stringResource(R.string.remote_commands))
103-
}
104-
)
105-
AssistChip(onClick = { setSheetContent("screencast") },
106-
leadingIcon = {
107-
Icon(
108-
painter = painterResource(R.drawable.terminal),
109-
contentDescription = stringResource(R.string.screencast)
110-
)
111-
},
112-
label = {
113-
Text(text = stringResource(R.string.screencast))
114-
}
115-
)
105+
LazyRow(
106+
modifier = Modifier.fillMaxWidth(),
107+
horizontalArrangement = Arrangement.spacedBy(8.dp)
108+
) {
109+
item {
110+
AssistChip(
111+
onClick = { setSheetContent("commands") },
112+
leadingIcon = {
113+
Icon(
114+
painter = painterResource(R.drawable.terminal),
115+
contentDescription = stringResource(R.string.remote_commands)
116+
)
117+
},
118+
label = {
119+
Text(text = stringResource(R.string.remote_commands))
120+
}
121+
)
122+
}
123+
item {
124+
AssistChip(
125+
onClick = { setSheetContent("screencast") },
126+
leadingIcon = {
127+
Icon(
128+
painter = painterResource(R.drawable.terminal),
129+
contentDescription = stringResource(R.string.screencast)
130+
)
131+
},
132+
label = {
133+
Text(text = stringResource(R.string.screencast))
134+
}
135+
)
136+
}
137+
item {
138+
AssistChip(
139+
onClick = closeConnection,
140+
leadingIcon = {
141+
Icon(
142+
imageVector = Icons.Default.Close,
143+
contentDescription = "Dangerous Action",
144+
tint = MaterialTheme.colorScheme.error
145+
)
146+
},
147+
label = {
148+
Text(
149+
text = stringResource(R.string.close),
150+
color = MaterialTheme.colorScheme.error
151+
)
152+
},
153+
)
154+
}
116155
}
117156
}
118157
}

app/src/main/java/dev/musakavak/uzayan/socket/ConnectionState.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,14 @@ class ConnectionState {
1313
var connectingStatus by mutableStateOf<Int?>(null)
1414
var remoteCommands by mutableStateOf<List<String>?>(null)
1515
var screens by mutableStateOf<List<Screen>?>(null)
16+
17+
fun setDefault(){
18+
currentStatus = 200
19+
connectedClientName = null
20+
isConnectionSecure = null
21+
connectingStatus = null
22+
remoteCommands = null
23+
screens = null
24+
}
1625
}
1726
}

app/src/main/java/dev/musakavak/uzayan/socket/Pair.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@ suspend fun sendPairRequest(
2222
val payload = PairObject(localPort, pairCode, name)
2323
val pairObject = NetworkMessage("Pair", payload)
2424

25-
val writer = PrintWriter(socket.getOutputStream())
26-
writer.println(Gson().toJson(pairObject))
27-
28-
writer.flush()
25+
val out = socket.getOutputStream()
26+
out.write(Gson().toJson(pairObject).toByteArray())
27+
out.flush()
2928
}
3029

app/src/main/java/dev/musakavak/uzayan/socket/Server.kt

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class Server(private val actions: Actions) {
1818
private var server: ServerSocket? = null
1919
val port get() = server?.localPort
2020
private val scope = CoroutineScope(Dispatchers.IO)
21+
private val activeSockets = mutableListOf<Socket>()
2122

2223
fun initialize(secureConnection: Boolean) {
2324
println("Creating Server")
@@ -33,13 +34,18 @@ class Server(private val actions: Actions) {
3334
if (server == null) return@launch
3435
while (!server!!.isClosed) {
3536
Log.w("Sockett Simple", "Listening for new client")
36-
val socket = server!!.accept()
37-
scope.launch {
38-
val address = "${socket?.inetAddress?.hostName}:${socket.port}"
39-
Log.w("Sockett Simple", "New Tcp Socket Connection From: $address")
40-
handleConnection(socket)
41-
Log.w("Sockett Simple", "Tcp Socket From: $address Is Disconnected")
42-
}
37+
try {
38+
val socket = server!!.accept()
39+
synchronized(activeSockets) {
40+
activeSockets.add(socket)
41+
}
42+
scope.launch {
43+
val address = "${socket?.inetAddress?.hostName}:${socket.port}"
44+
Log.w("Sockett Simple", "New Tcp Socket Connection From: $address")
45+
handleConnection(socket)
46+
Log.w("Sockett Simple", "Tcp Socket From: $address Is Disconnected")
47+
}
48+
}catch (_:Exception){}
4349
}
4450
}
4551
}
@@ -154,6 +160,17 @@ class Server(private val actions: Actions) {
154160
}
155161

156162
fun close() {
163+
synchronized(activeSockets) {
164+
activeSockets.forEach { socket ->
165+
try {
166+
socket.close()
167+
} catch (e: Exception) {
168+
Log.e("Sockett Simple", "Error closing socket: ${e.message}")
169+
}
170+
}
171+
activeSockets.clear()
172+
}
173+
157174
scope.cancel()
158175
server?.close()
159176
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@
3939
<string name="permission_storage_text">With this permission, you can transfer files between your devices.</string>
4040
<string name="invalid_qr_code">Invalid QR Code</string>
4141
<string name="permission_denied">Permission Denied</string>
42+
<string name="close">Close</string>
4243
</resources>

0 commit comments

Comments
 (0)