This commit is contained in:
Андрей Дувакин 2025-01-27 20:07:40 +05:00
parent e69c47ca4b
commit dcef23b404
3 changed files with 391 additions and 133 deletions

View File

@ -4,6 +4,7 @@ import random
import feedparser import feedparser
import jwt import jwt
from sqlalchemy import desc
from data.connect import init_db, connect, User, Document, DocumentCategory, Comment, Event from data.connect import init_db, connect, User, Document, DocumentCategory, Comment, Event
from flask import Flask, Response, request, jsonify from flask import Flask, Response, request, jsonify
@ -315,7 +316,7 @@ def get_events():
resp = [] resp = []
with connect() as session: with connect() as session:
events = session.query(Event).all() events = session.query(Event).order_by(desc(Event.datetime_event)).all()
users = session.query(User).all() users = session.query(User).all()
for event in events: for event in events:

View File

@ -30,4 +30,24 @@ object API {
} }
} }
} }
@OptIn(DelicateCoroutinesApi::class)
fun getEvents(onFinish: (String) -> Unit) {
GlobalScope.launch(Dispatchers.IO) {
val reqURL = URL("$API_BASE_URL/events")
val connection = reqURL.openConnection() as HttpURLConnection
connection.requestMethod = "GET"
if (connection.responseCode == 200) {
val resp = BufferedReader(
InputStreamReader(connection.inputStream)
).use { it.readText() }
onFinish(resp)
} else {
onFinish("Error")
}
}
}
} }

View File

@ -1,5 +1,6 @@
package com.example.russionroadsapp package com.example.russionroadsapp
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.widget.Toast import android.widget.Toast
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
@ -17,6 +18,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
@ -26,6 +28,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Star
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonColors
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@ -41,6 +44,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
@ -57,163 +61,396 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
val listState = rememberLazyListState() var pageName by remember {
val coroutineScope = rememberCoroutineScope() mutableStateOf("News")
var messageToast by remember {
mutableStateOf("")
} }
var newsList by remember { fun setPageNews() {
mutableStateOf(listOf<Map<String, String>>()) pageName = "News"
} }
var requestNews by remember { fun setPageEvents() {
mutableStateOf(true) pageName = "Events"
} }
var newsString by remember { if (pageName == "News") {
mutableStateOf("") NewsPage(
}
if (messageToast != "") {
Toast.makeText(
this@MainActivity, this@MainActivity,
messageToast, {
Toast.LENGTH_LONG setPageNews()
).show() },
messageToast = "" {
setPageEvents()
},
)
} else {
EventsPage(
this@MainActivity,
{
setPageNews()
},
{
setPageEvents()
},
)
} }
}
}
}
LaunchedEffect(requestNews) { @Composable
if (requestNews) { fun EventCard(event: Map<String, String>) {
API.getNews { resp -> Column(
if (resp != "Error") { Modifier
newsString = resp .clip(RoundedCornerShape(10.dp))
} else { .size(300.dp, 90.dp)
messageToast = "Ошибка при получении новостей" .background(Color(64, 208, 25, 255))
} .padding(10.dp),
} verticalArrangement = Arrangement.SpaceAround,
) {
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text("")
Column {
event["title"]?.let { Text(it) }
event["description"]?.let { Text(it) }
}
Icon(Icons.Default.Star, contentDescription = "")
}
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
event["date"]?.let { Text(it) }
event["author"]?.let { Text(it) }
}
}
}
@Composable
fun EventsPage(localContext: Context, setPageNews: () -> Unit, setPageEvents: () -> Unit) {
val listState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
var requestEvents by remember {
mutableStateOf(true)
}
var eventsString by remember {
mutableStateOf("")
}
var messageToast by remember {
mutableStateOf("")
}
var eventsList by remember {
mutableStateOf(listOf<Map<String, String>>())
}
if (messageToast != "") {
Toast.makeText(
localContext,
messageToast,
Toast.LENGTH_LONG
).show()
messageToast = ""
}
LaunchedEffect(requestEvents) {
if (requestEvents) {
API.getEvents { resp ->
if (resp != "Error") {
eventsString = resp
} else {
messageToast = "Ошибка при получении событий"
} }
} }
requestEvents = false
}
}
LaunchedEffect(newsString) { LaunchedEffect(eventsString) {
if (newsString != "") { if (eventsString != "") {
val gson = Gson() val gson = Gson()
val dataType = object : TypeToken<List<Map<String, String>>>() {}.type val dataType = object : TypeToken<List<Map<String, String>>>() {}.type
val data: List<Map<String, String>> = gson.fromJson( val data: List<Map<String, String>> = gson.fromJson(
newsString, eventsString,
dataType dataType
) )
newsList = data eventsList = data
newsString = "" eventsString = ""
println(data) println(data)
} }
} }
Column( Column(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.background(Color(72, 103, 48, 255)), .background(Color(72, 103, 48, 255)),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(Modifier.padding(20.dp))
Row {
Button(
{
setPageNews()
},
colors = ButtonColors(
containerColor = Color.Red,
contentColor = Color.Black,
disabledContentColor = Color.Black,
disabledContainerColor = Color.Red
),
modifier = Modifier
.padding(10.dp)
.size(150.dp, 70.dp),
shape = RectangleShape
) { ) {
Text("новости")
}
Spacer(Modifier.padding(20.dp)) Button(
{
setPageEvents()
},
colors = ButtonColors(
containerColor = Color.Yellow,
contentColor = Color.Black,
disabledContentColor = Color.Yellow,
disabledContainerColor = Color.Red
),
modifier = Modifier
.padding(10.dp)
.size(150.dp, 70.dp),
shape = RectangleShape
) {
Text("события")
}
}
Row { Column(
Modifier
.fillMaxSize()
.padding(20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Button( Icon(
{ Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "",
}, modifier = Modifier
colors = ButtonColors( .clip(CircleShape)
containerColor = Color.Red, .clickable {
contentColor = Color.Black, coroutineScope.launch {
disabledContentColor = Color.Black, val targetIndex = (listState.firstVisibleItemIndex - 1).coerceAtLeast(0)
disabledContainerColor = Color.Red listState.animateScrollToItem(targetIndex)
),
modifier = Modifier
.padding(10.dp)
.size(150.dp, 70.dp),
shape = RectangleShape
) {
Text("новости")
}
Button(
{
},
colors = ButtonColors(
containerColor = Color.Yellow,
contentColor = Color.Black,
disabledContentColor = Color.Yellow,
disabledContainerColor = Color.Red
),
modifier = Modifier
.padding(10.dp)
.size(150.dp, 70.dp),
shape = RectangleShape
) {
Text("события")
}
}
Row(
Modifier
.fillMaxSize()
.padding(20.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "",
modifier = Modifier
.clip(CircleShape)
.clickable {
coroutineScope.launch {
val targetIndex = (listState.firstVisibleItemIndex - 1).coerceAtLeast(0)
listState.animateScrollToItem(targetIndex)
}
}
.padding(20.dp)
.weight(1f)
)
LazyRow(
state = listState,
modifier = Modifier.weight(4f),
horizontalArrangement = Arrangement.spacedBy(20.dp)
) {
items(newsList.size) { index ->
NewsCard(newsList[index])
} }
} }
.rotate(90f)
.padding(20.dp)
.weight(1f)
)
Icon( LazyColumn(
Icons.AutoMirrored.Filled.ArrowForward, state = listState,
contentDescription = "", modifier = Modifier.weight(4f),
modifier = Modifier verticalArrangement = Arrangement.spacedBy(20.dp)
.clip(CircleShape) ) {
.clickable { items(eventsList.size) { index ->
coroutineScope.launch { EventCard(eventsList[index])
val targetIndex =
(listState.firstVisibleItemIndex + 1).coerceAtMost(newsList.size - 1)
listState.animateScrollToItem(targetIndex)
}
}
.padding(20.dp)
.weight(1f)
)
} }
} }
Icon(
Icons.AutoMirrored.Filled.ArrowForward,
contentDescription = "",
modifier = Modifier
.clip(CircleShape)
.clickable {
coroutineScope.launch {
val targetIndex =
(listState.firstVisibleItemIndex + 1).coerceAtMost(eventsList.size - 1)
listState.animateScrollToItem(targetIndex)
}
}
.padding(20.dp)
.rotate(90f)
.weight(1f)
)
} }
}
}
@Composable
fun NewsPage(localContext: Context, setPageNews: () -> Unit, setPageEvents: () -> Unit) {
val listState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
var messageToast by remember {
mutableStateOf("")
}
var newsList by remember {
mutableStateOf(listOf<Map<String, String>>())
}
var requestNews by remember {
mutableStateOf(true)
}
var newsString by remember {
mutableStateOf("")
}
if (messageToast != "") {
Toast.makeText(
localContext,
messageToast,
Toast.LENGTH_LONG
).show()
messageToast = ""
}
LaunchedEffect(requestNews) {
if (requestNews) {
API.getNews { resp ->
if (resp != "Error") {
newsString = resp
} else {
messageToast = "Ошибка при получении новостей"
}
}
}
}
LaunchedEffect(newsString) {
if (newsString != "") {
val gson = Gson()
val dataType = object : TypeToken<List<Map<String, String>>>() {}.type
val data: List<Map<String, String>> = gson.fromJson(
newsString,
dataType
)
newsList = data
newsString = ""
println(data)
}
}
Column(
Modifier
.fillMaxSize()
.background(Color(72, 103, 48, 255)),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(Modifier.padding(20.dp))
Row {
Button(
{
setPageNews()
},
colors = ButtonColors(
containerColor = Color.Red,
contentColor = Color.Black,
disabledContentColor = Color.Black,
disabledContainerColor = Color.Red
),
modifier = Modifier
.padding(10.dp)
.size(150.dp, 70.dp),
shape = RectangleShape
) {
Text("новости")
}
Button(
{
setPageEvents()
},
colors = ButtonColors(
containerColor = Color.Yellow,
contentColor = Color.Black,
disabledContentColor = Color.Yellow,
disabledContainerColor = Color.Red
),
modifier = Modifier
.padding(10.dp)
.size(150.dp, 70.dp),
shape = RectangleShape
) {
Text("события")
}
}
Row(
Modifier
.fillMaxSize()
.padding(20.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "",
modifier = Modifier
.clip(CircleShape)
.clickable {
coroutineScope.launch {
val targetIndex = (listState.firstVisibleItemIndex - 1).coerceAtLeast(0)
listState.animateScrollToItem(targetIndex)
}
}
.padding(20.dp)
.weight(1f)
)
LazyRow(
state = listState,
modifier = Modifier.weight(4f),
horizontalArrangement = Arrangement.spacedBy(20.dp)
) {
items(newsList.size) { index ->
NewsCard(newsList[index])
}
}
Icon(
Icons.AutoMirrored.Filled.ArrowForward,
contentDescription = "",
modifier = Modifier
.clip(CircleShape)
.clickable {
coroutineScope.launch {
val targetIndex =
(listState.firstVisibleItemIndex + 1).coerceAtMost(newsList.size - 1)
listState.animateScrollToItem(targetIndex)
}
}
.padding(20.dp)
.weight(1f)
)
}
} }
} }