Skip to content

Commit e18c96c

Browse files
committed
beta 3 soon
1 parent 746a54e commit e18c96c

28 files changed

+857
-186
lines changed

.idea/deploymentTargetDropDown.xml

Lines changed: 1 addition & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/build.gradle.kts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
plugins {
33
alias(libs.plugins.androidApplication)
44
alias(libs.plugins.kotlinAndroid)
5+
id("io.sentry.android.gradle") version "3.11.1"
56
}
67

78
android {
@@ -62,6 +63,14 @@ android {
6263

6364
dependencies {
6465
// TPU
66+
67+
implementation("io.noties.markwon:core:4.6.2")
68+
implementation("io.noties.markwon:ext-strikethrough:4.6.2")
69+
implementation("io.noties.markwon:ext-tables:4.6.2")
70+
implementation("io.noties.markwon:html:4.6.2")
71+
implementation("io.noties.markwon:linkify:4.6.2")
72+
implementation("io.sentry:sentry-android:6.23.0")
73+
implementation("io.sentry:sentry-compose-android:6.23.0")
6574
implementation("androidx.compose.runtime:runtime-tracing:1.0.0-alpha03")
6675
implementation("io.coil-kt:coil-gif:2.4.0")
6776
implementation("io.coil-kt:coil-compose:2.4.0")

app/release/app-release.apk

4.63 MB
Binary file not shown.

app/release/output-metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"type": "SINGLE",
1212
"filters": [],
1313
"attributes": [],
14-
"versionCode": 1,
14+
"versionCode": 2,
1515
"versionName": "1.0.2",
1616
"outputFile": "app-release.apk"
1717
}

app/src/main/AndroidManifest.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,20 @@
1414
android:theme="@style/Theme.PrivateUploader"
1515
android:usesCleartextTraffic="true"
1616
tools:targetApi="31">
17+
<!-- Required: set your sentry.io project identifier (DSN) -->
18+
<meta-data android:name="io.sentry.dsn" android:value="https://[email protected]/4505429578874880" />
19+
20+
<!-- enable automatic breadcrumbs for user interactions (clicks, swipes, scrolls) -->
21+
<meta-data android:name="io.sentry.traces.user-interaction.enable" android:value="true" />
22+
<!-- enable screenshot for crashes -->
23+
<meta-data android:name="io.sentry.attach-screenshot" android:value="true" />
24+
<!-- enable view hierarchy for crashes -->
25+
<meta-data android:name="io.sentry.attach-view-hierarchy" android:value="true" />
26+
27+
<!-- enable the performance API by setting a sample-rate, adjust in production env -->
28+
<meta-data android:name="io.sentry.traces.sample-rate" android:value="1.0" />
29+
<!-- enable profiling when starting transactions, adjust in production env -->
30+
<meta-data android:name="io.sentry.traces.profiling.sample-rate" android:value="1.0" />
1731
<activity
1832
android:name=".MainActivity"
1933
android:exported="true"

app/src/main/java/com/troplo/privateuploader/MainScreen.kt

Lines changed: 88 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import androidx.compose.runtime.getValue
1818
import androidx.compose.runtime.mutableStateOf
1919
import androidx.compose.runtime.remember
2020
import androidx.compose.runtime.setValue
21+
import androidx.compose.ui.ExperimentalComposeUiApi
2122
import androidx.compose.ui.Modifier
2223
import androidx.compose.ui.platform.LocalContext
2324
import androidx.compose.ui.unit.dp
@@ -37,99 +38,107 @@ import com.troplo.privateuploader.components.core.TopBarNav
3738
import com.troplo.privateuploader.components.core.rememberOverlappingPanelsState
3839
import com.troplo.privateuploader.data.model.User
3940
import com.troplo.privateuploader.screens.HomeScreen
41+
import io.sentry.compose.SentryTraced
4042

41-
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
43+
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class,
44+
ExperimentalComposeUiApi::class
45+
)
4246
@Composable
4347
fun MainScreen() {
44-
val user = UserStore.user.collectAsState()
45-
val context = LocalContext.current
46-
val navController = rememberNavController()
47-
val panelState = rememberOverlappingPanelsState()
48-
var closePanels by remember { mutableStateOf(false) }
49-
// track socket connection status
50-
val closePanelsFunc = {
51-
closePanels = true
52-
}
53-
if (closePanels) {
54-
LaunchedEffect(Unit) {
55-
panelState.closePanels()
56-
closePanels = false
48+
SentryTraced("main") {
49+
val user = UserStore.user.collectAsState()
50+
val context = LocalContext.current
51+
val navController = rememberNavController()
52+
val panelState = rememberOverlappingPanelsState()
53+
var closePanels by remember { mutableStateOf(false) }
54+
val closePanelsFunc = {
55+
closePanels = true
5756
}
58-
}
59-
Scaffold(
60-
topBar = {
61-
if (!SocketHandler.connected.value) {
62-
ConnectingBanner()
63-
} else {
64-
TopBarNav(navController = navController, user = user.value, panelState = panelState)
57+
if (closePanels) {
58+
LaunchedEffect(Unit) {
59+
panelState.closePanels()
60+
closePanels = false
6561
}
66-
},
67-
bottomBar = {
68-
BottomBarNav(
69-
navController = navController,
70-
panelState = panelState,
71-
closePanels = closePanelsFunc
72-
)
73-
},
74-
) { paddingValues ->
75-
OverlappingPanels(
76-
modifier = Modifier.fillMaxSize(),
77-
panelsState = panelState,
78-
gesturesEnabled = navController.currentDestination?.route?.startsWith("chat/") == true,
79-
panelStart = {
80-
PanelSurface {
81-
ModalDrawerSheet(
82-
modifier = Modifier.padding(
83-
top = paddingValues.calculateTopPadding(),
84-
bottom = paddingValues.calculateBottomPadding()
85-
)
86-
) {
87-
Spacer(Modifier.height(12.dp))
88-
HomeScreen(
89-
openChat = { chatId ->
90-
ChatStore.setAssociationId(chatId, context)
91-
navController.navigate("${NavRoute.Chat.path}/$chatId")
92-
closePanels = true
93-
},
94-
panelState = panelState
95-
)
96-
}
97-
}
98-
},
99-
panelCenter = {
100-
PanelSurface {
101-
NavGraph(
102-
modifier = Modifier.padding(
103-
top = paddingValues.calculateTopPadding(),
104-
bottom = paddingValues.calculateBottomPadding()
105-
),
62+
}
63+
Scaffold(
64+
topBar = {
65+
if (!SocketHandler.connected.value) {
66+
ConnectingBanner()
67+
} else {
68+
TopBarNav(
10669
navController = navController,
10770
user = user.value,
108-
context,
109-
panelsState = panelState
71+
panelState = panelState
11072
)
11173
}
11274
},
113-
panelEnd = {
114-
PanelSurface {
115-
ModalDrawerSheet(
116-
modifier = Modifier.padding(
117-
top = paddingValues.calculateTopPadding(),
118-
bottom = paddingValues.calculateBottomPadding()
119-
)
120-
) {
121-
Column(
122-
modifier = Modifier
123-
.verticalScroll(rememberScrollState())
124-
.weight(weight = 1f, fill = false)
125-
75+
bottomBar = {
76+
BottomBarNav(
77+
navController = navController,
78+
panelState = panelState,
79+
closePanels = closePanelsFunc
80+
)
81+
},
82+
) { paddingValues ->
83+
OverlappingPanels(
84+
modifier = Modifier.fillMaxSize(),
85+
panelsState = panelState,
86+
gesturesEnabled = navController.currentDestination?.route?.startsWith("chat/") == true,
87+
panelStart = {
88+
PanelSurface {
89+
ModalDrawerSheet(
90+
modifier = Modifier.padding(
91+
top = paddingValues.calculateTopPadding(),
92+
bottom = paddingValues.calculateBottomPadding()
93+
)
12694
) {
12795
Spacer(Modifier.height(12.dp))
128-
MemberSidebar()
96+
HomeScreen(
97+
openChat = { chatId ->
98+
ChatStore.setAssociationId(chatId, context)
99+
navController.navigate("${NavRoute.Chat.path}/$chatId")
100+
closePanels = true
101+
},
102+
panelState = panelState
103+
)
104+
}
105+
}
106+
},
107+
panelCenter = {
108+
PanelSurface {
109+
NavGraph(
110+
modifier = Modifier.padding(
111+
top = paddingValues.calculateTopPadding(),
112+
bottom = if(navController.currentDestination?.route?.startsWith("chat/") == true) 0.dp else paddingValues.calculateBottomPadding()
113+
),
114+
navController = navController,
115+
user = user.value,
116+
context,
117+
panelsState = panelState
118+
)
119+
}
120+
},
121+
panelEnd = {
122+
PanelSurface {
123+
ModalDrawerSheet(
124+
modifier = Modifier.padding(
125+
top = paddingValues.calculateTopPadding(),
126+
bottom = paddingValues.calculateBottomPadding()
127+
)
128+
) {
129+
Column(
130+
modifier = Modifier
131+
.verticalScroll(rememberScrollState())
132+
.weight(weight = 1f, fill = false)
133+
134+
) {
135+
Spacer(Modifier.height(12.dp))
136+
MemberSidebar()
137+
}
129138
}
130139
}
131140
}
132-
}
133-
)
141+
)
142+
}
134143
}
135144
}

app/src/main/java/com/troplo/privateuploader/api/ApiService.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.widget.Toast
77
import com.troplo.privateuploader.BuildConfig
88
import com.troplo.privateuploader.data.model.Chat
99
import com.troplo.privateuploader.data.model.EditRequest
10+
import com.troplo.privateuploader.data.model.Friend
1011
import com.troplo.privateuploader.data.model.Gallery
1112
import com.troplo.privateuploader.data.model.LoginRequest
1213
import com.troplo.privateuploader.data.model.LoginResponse
@@ -160,6 +161,7 @@ object TpuApi {
160161
@GET("chats/{id}/messages")
161162
fun getMessages(
162163
@Path("id") id: Int,
164+
@Query("offset") offset: Int? = null
163165
): Call<List<Message>>
164166

165167
@POST("chats/{id}/message")
@@ -184,6 +186,14 @@ object TpuApi {
184186
@Path("chatId") chatId: Int,
185187
@Path("messageId") messageId: Int,
186188
): Call<Unit>
189+
190+
@GET("user/profile/{username}")
191+
fun getUserProfile(
192+
@Path("username") username: String
193+
): Call<User>
194+
195+
@GET("user/friends")
196+
fun getFriends(): Call<List<Friend>>
187197
}
188198

189199
val retrofitService: TpuApiService by lazy {

app/src/main/java/com/troplo/privateuploader/api/Functions.kt

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
package com.troplo.privateuploader.api
22

3-
import android.text.format.DateFormat
43
import com.troplo.privateuploader.data.model.Chat
54
import com.troplo.privateuploader.data.model.User
6-
import java.util.Date
5+
import java.text.DateFormat
6+
import java.text.SimpleDateFormat
7+
import java.time.LocalDate
8+
import java.time.ZoneId
9+
import java.time.ZoneOffset
10+
import java.time.ZonedDateTime
11+
import java.time.format.DateTimeFormatter
12+
import java.util.Calendar
13+
import java.util.Locale
714
import kotlin.math.ln
815
import kotlin.math.pow
916

@@ -33,11 +40,43 @@ object TpuFunctions {
3340
}
3441
}
3542

36-
fun formatDate(date: Date?): CharSequence? {
37-
if (DateFormat.format("dd MMMM yyyy", date) == DateFormat.format("dd MMMM yyyy", Date())) {
38-
return DateFormat.format("hh:mm:ss a", date)
43+
44+
45+
fun formatDate(date: String?): CharSequence {
46+
try {
47+
val utcDateTime = ZonedDateTime.parse(date)
48+
val localDateTime = utcDateTime.withZoneSameInstant(ZoneId.systemDefault())
49+
val currentDate = LocalDate.now()
50+
51+
val formatter = if (localDateTime.toLocalDate() == currentDate) {
52+
DateTimeFormatter.ofPattern("hh:mm:ss a")
53+
} else {
54+
DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm:ss a")
55+
}
56+
57+
return localDateTime.format(formatter)
58+
} catch (e: Exception) {
59+
println("Error formatting date (FD): $e")
60+
return "Check logcat"
61+
}
62+
}
63+
64+
fun formatDateDay(date: String?): CharSequence {
65+
try {
66+
val utcDateTime = ZonedDateTime.parse(date)
67+
val localDateTime = utcDateTime.withZoneSameInstant(ZoneId.systemDefault())
68+
69+
val formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy")
70+
71+
return localDateTime.format(formatter)
72+
} catch (e: Exception) {
73+
println("Error formatting date (FDD): $e")
74+
return "Check logcat"
3975
}
40-
return DateFormat.format("dd MMMM yyyy, hh:mm:ss a", date)
76+
}
77+
78+
fun currentISODate(): String {
79+
return ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)
4180
}
4281

4382
fun fileSize(size: Int?): String {
@@ -48,4 +87,14 @@ object TpuFunctions {
4887
val pre = "KMGTPE"[exp - 1] + "i"
4988
return String.format("%.1f %sB", size / unit.toDouble().pow(exp.toDouble()), pre)
5089
}
90+
91+
fun getStatusDetails(status: String): Pair<Long, String> {
92+
return when (status) {
93+
"online" -> Pair(0xFF4CAF50, "Online")
94+
"idle" -> Pair(0xFFFF9800, "Idle")
95+
"busy" -> Pair(0xFFF44336, "Do Not Disturb")
96+
"invisible" -> Pair(0xFF757575, "Invisible")
97+
else -> Pair(0xFF757575, "Offline")
98+
}
99+
}
51100
}

app/src/main/java/com/troplo/privateuploader/api/SocketHandler.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ object SocketHandler {
2121
private const val SERVER_URL = BuildConfig.SERVER_URL
2222

2323
private var socket: Socket? = null
24-
private val gson = Gson()
24+
val gson = Gson()
2525
var connected = mutableStateOf(false)
2626

2727
fun initializeSocket(token: String, context: Context) {

0 commit comments

Comments
 (0)