10 Commits

Author SHA1 Message Date
Shcherbatykh Oleg
59c869d539 fix locale in parser 2026-02-27 11:37:49 +03:00
Shcherbatykh Oleg
082c4f7973 enable news func 2026-02-27 11:35:37 +03:00
Shcherbatykh Oleg
c2efbd1f75 Merge branch 'develop' of https://github.com/finocd2la/TSUDesk into feature/news-ui 2026-02-27 11:32:55 +03:00
Shcherbatykh Oleg
0482f03e09 Temp. disabled news 2026-02-27 11:32:36 +03:00
Shcherbatykh Oleg
aff43c61a0 update base and schedule url 2026-02-27 11:31:22 +03:00
Shcherbatykh Oleg
2987289581 Merge branch 'develop' of https://github.com/finocd2la/TSUDesk into feature/news-ui 2026-02-27 11:22:18 +03:00
Shcherbatykh Oleg
aaed01bd12 Change icon type 2026-02-27 11:21:03 +03:00
Shcherbatykh Oleg
39ff86c8a0 Merge branch 'develop' of https://github.com/finocd2la/TSUDesk into feature/news-ui 2026-02-27 11:03:07 +03:00
Shcherbatykh Oleg
993ab0a0b1 merge fix 2026-02-27 11:01:47 +03:00
Shcherbatykh Oleg
1f6e7b8ac0 update app navigation 2026-02-27 11:00:07 +03:00
14 changed files with 110 additions and 121 deletions

View File

@@ -14,7 +14,7 @@ private const val BASE_TIMEOUT = 30L
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
object AppConfigModule { object AppConfigModule {
private const val BASE_URL_PROD = "https://tulsu.ru/schedule/queries/" private const val BASE_URL_PROD = "https://tulsu.ru/"
private const val BASE_URL_DEVELOP = "https://scherbatykh.ru/app/tsudesk/" private const val BASE_URL_DEVELOP = "https://scherbatykh.ru/app/tsudesk/"
@Provides @Provides

View File

@@ -1,37 +1,32 @@
package ru.fincode.tsudesk.app.presentation.main package ru.fincode.tsudesk.presentation.main
import androidx.navigation.NavBackStackEntry import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hasRoute
import ru.fincode.tsudesk.core.navigation.AppRoute import ru.fincode.tsudesk.core.navigation.AppRoute
import ru.fincode.tsudesk.core.navigation.TopLevelDestination import ru.fincode.tsudesk.core.navigation.TopLevelDestination
import ru.fincode.tsudesk.core.navigation.route
fun selectedTopLevel(entry: NavBackStackEntry?): TopLevelDestination { fun selectedTopLevel(entry: NavBackStackEntry?): TopLevelDestination {
if (entry == null) return TopLevelDestination.SCHEDULE val dest: NavDestination = entry?.destination ?: return TopLevelDestination.SCHEDULE
return runCatching { return when {
when (entry.route<AppRoute>()) { dest.hasRoute<AppRoute.Schedule>() || dest.hasRoute<AppRoute.ScheduleDetails>() ->
AppRoute.Schedule, TopLevelDestination.SCHEDULE
is AppRoute.ScheduleDetails -> TopLevelDestination.SCHEDULE
AppRoute.News, dest.hasRoute<AppRoute.News>() || dest.hasRoute<AppRoute.NewsDetails>() ->
is AppRoute.NewsDetails -> TopLevelDestination.NEWS TopLevelDestination.NEWS
AppRoute.Progress -> TopLevelDestination.PROGRESS dest.hasRoute<AppRoute.Progress>() ->
TopLevelDestination.PROGRESS
AppRoute.Settings -> TopLevelDestination.SETTINGS dest.hasRoute<AppRoute.Settings>() ->
TopLevelDestination.SETTINGS
else -> TopLevelDestination.SCHEDULE else -> TopLevelDestination.SCHEDULE
} }
}.getOrDefault(TopLevelDestination.SCHEDULE)
} }
fun shouldShowBottomBar(entry: NavBackStackEntry?): Boolean { fun shouldShowBottomBar(entry: NavBackStackEntry?): Boolean {
if (entry == null) return false val dest: NavDestination = entry?.destination ?: return false
return !dest.hasRoute<AppRoute.Splash>()
return runCatching {
when (entry.route<AppRoute>()) {
AppRoute.Splash -> false
else -> true
}
}.getOrDefault(true)
} }

View File

@@ -5,15 +5,13 @@ import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import ru.fincode.core.ui.components.BottomBarItem import ru.fincode.core.ui.components.BottomBarItem
import ru.fincode.core.ui.components.TsudeskBottomBar import ru.fincode.core.ui.components.TsudeskBottomBar
import ru.fincode.tsudesk.R import ru.fincode.tsudesk.R
import ru.fincode.tsudesk.app.presentation.main.selectedTopLevel
import ru.fincode.tsudesk.app.presentation.main.shouldShowBottomBar
import ru.fincode.tsudesk.core.navigation.TopLevelDestination import ru.fincode.tsudesk.core.navigation.TopLevelDestination
import ru.fincode.tsudesk.core.navigation.navigateToTopLevel import ru.fincode.tsudesk.core.navigation.navigateToTopLevel
@@ -22,32 +20,20 @@ fun MainScaffold(
navController: NavHostController, navController: NavHostController,
content: @Composable (Modifier) -> Unit, content: @Composable (Modifier) -> Unit,
) { ) {
val scheduleIcon = painterResource(R.drawable.ic_progress) val scheduleIcon =
val newsIcon = painterResource(R.drawable.ic_news) androidx.compose.ui.graphics.vector.ImageVector.vectorResource(R.drawable.ic_progress)
val progressIcon = painterResource(R.drawable.ic_progress) val newsIcon =
val settingsIcon = painterResource(R.drawable.ic_progress) androidx.compose.ui.graphics.vector.ImageVector.vectorResource(R.drawable.ic_progress)
val progressIcon =
androidx.compose.ui.graphics.vector.ImageVector.vectorResource(R.drawable.ic_progress)
val settingsIcon =
androidx.compose.ui.graphics.vector.ImageVector.vectorResource(R.drawable.ic_progress)
val items = listOf( val items = listOf(
TopLevelItem( TopLevelItem(TopLevelDestination.SCHEDULE, R.string.tab_schedule, scheduleIcon),
destination = TopLevelDestination.SCHEDULE, TopLevelItem(TopLevelDestination.NEWS, R.string.tab_news, newsIcon),
labelRes = R.string.tab_schedule, TopLevelItem(TopLevelDestination.PROGRESS, R.string.tab_progress, progressIcon),
icon = scheduleIcon TopLevelItem(TopLevelDestination.SETTINGS, R.string.tab_settings, settingsIcon),
),
TopLevelItem(
destination = TopLevelDestination.NEWS,
labelRes = R.string.tab_news,
icon = newsIcon
),
TopLevelItem(
destination = TopLevelDestination.PROGRESS,
labelRes = R.string.tab_progress,
icon = progressIcon
),
TopLevelItem(
destination = TopLevelDestination.SETTINGS,
labelRes = R.string.tab_settings,
icon = settingsIcon
),
) )
val backStackEntry by navController.currentBackStackEntryAsState() val backStackEntry by navController.currentBackStackEntryAsState()

View File

@@ -1,12 +1,11 @@
package ru.fincode.tsudesk.presentation.main package ru.fincode.tsudesk.presentation.main
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import ru.fincode.tsudesk.core.navigation.TopLevelDestination import ru.fincode.tsudesk.core.navigation.TopLevelDestination
data class TopLevelItem( data class TopLevelItem(
val destination: TopLevelDestination, val destination: TopLevelDestination,
@StringRes val labelRes: Int, @StringRes val labelRes: Int,
val icon: Painter, val icon: ImageVector
) )

View File

@@ -1,19 +1,20 @@
package ru.fincode.tsudesk.presentation.navigation package ru.fincode.tsudesk.presentation.navigation
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation import androidx.navigation.compose.rememberNavController
import ru.fincode.tsudesk.presentation.main.MainScaffold
import ru.fincode.tsudesk.core.navigation.AppRoute import ru.fincode.tsudesk.core.navigation.AppRoute
import ru.fincode.tsudesk.core.navigation.navigateRoute import ru.fincode.tsudesk.core.navigation.navigateRoute
import ru.fincode.tsudesk.feature.news.presentation.screen.NewsRoute
//import ru.fincode.tsudesk.feature.news.presentation.screen.NewsRoute
import ru.fincode.tsudesk.presentation.main.MainScaffold
import ru.fincode.tsudesk.feature.schedule.presentation.screen.ScheduleRoute import ru.fincode.tsudesk.feature.schedule.presentation.screen.ScheduleRoute
import ru.fincode.tsudesk.feature.splash.presentation.screen.SplashRoute import ru.fincode.tsudesk.feature.splash.presentation.screen.SplashRoute
@Composable @Composable
fun AppNavHost( fun AppNavHost(
navController: NavHostController, navController: NavHostController,
@@ -33,51 +34,45 @@ fun AppNavHost(
) )
} }
navigation<AppRoute.Main>(startDestination = AppRoute.Schedule) { composable<AppRoute.Main> {
val tabsNavController = rememberNavController()
composable<AppRoute.Schedule> { MainScaffold(
MainScaffold(navController) { innerModifier -> navController = tabsNavController
ScheduleRoute( ) { innerModifier ->
modifier = innerModifier, MainTabsNavHost(
// onOpenDetails = { lessonId -> navController = tabsNavController,
// navController.navigateRoute(AppRoute.ScheduleDetails(lessonId)) modifier = innerModifier
// } )
)
}
} }
}
}
}
composable<AppRoute.News> { @Composable
MainScaffold(navController) { innerModifier: Modifier -> private fun MainTabsNavHost(
// NewsScreen( navController: NavHostController,
// modifier = innerModifier, modifier: Modifier = Modifier,
// onOpenDetails = { id -> ) {
// navController.navigateRoute(AppRoute.NewsDetails(id)) NavHost(
// } navController = navController,
// ) startDestination = AppRoute.Schedule,
} modifier = modifier
} ) {
composable<AppRoute.Schedule> {
ScheduleRoute(modifier = Modifier.fillMaxSize())
}
composable<AppRoute.Progress> { composable<AppRoute.News> {
MainScaffold(navController) { innerModifier: Modifier -> NewsRoute(modifier = Modifier.fillMaxSize())
// ProgressScreen(modifier = innerModifier) }
}
}
composable<AppRoute.Settings> { composable<AppRoute.Progress> {
MainScaffold(navController) { innerModifier -> // ProgressRoute(modifier = Modifier)
// SettingsRoute(modifier = innerModifier) }
}
} composable<AppRoute.Settings> {
// // SettingsRoute(modifier = Modifier)
// composable<AppRoute.ScheduleDetails> { entry ->
// val args = entry.route<AppRoute.ScheduleDetails>()
// ScheduleDetailsScreen(lessonId = args.lessonId)
// }
//
// composable<AppRoute.NewsDetails> { entry ->
// val args = entry.route<AppRoute.NewsDetails>()
// NewsDetailsScreen(id = args.id)
// }
} }
} }
} }

View File

@@ -3,10 +3,12 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <path
android:pathData="M12,3L1,9l11,6 9,-4.91V17h2V9L12,3z" android:pathData="M12,3L1,9l11,6 9,-4.91V17h2V9L12,3z"
android:fillColor="?attr/colorControlNormal"/> android:fillColor="#FF000000"/>
<path <path
android:pathData="M5,12.18V17c0,2.21 3.58,4 7,4s7,-1.79 7,-4v-4.82l-7,3.82 -7,-3.82z" android:pathData="M5,12.18V17c0,2.21 3.58,4 7,4s7,-1.79 7,-4v-4.82l-7,3.82 -7,-3.82z"
android:fillColor="?attr/colorControlNormal"/> android:fillColor="#FF000000"/>
</vector> </vector>

View File

@@ -13,7 +13,6 @@ import ru.fincode.tsudesk.core.database.api.schedule.ScheduleDao
LessonCacheEntity::class LessonCacheEntity::class
], ],
version = 2, version = 2,
exportSchema = true
) )
@TypeConverters(StringListConverter::class) @TypeConverters(StringListConverter::class)
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {

View File

@@ -0,0 +1,9 @@
package ru.fincode.core.ui.components
import androidx.compose.ui.graphics.vector.ImageVector
data class BottomBarItem(
val key: String,
val label: String,
val icon: ImageVector,
)

View File

@@ -1,17 +1,11 @@
package ru.fincode.core.ui.components package ru.fincode.core.ui.components
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.painter.Painter
data class BottomBarItem(
val key: String,
val label: String,
val icon: Painter,
)
@Composable @Composable
fun TsudeskBottomBar( fun TsudeskBottomBar(
@@ -21,19 +15,22 @@ fun TsudeskBottomBar(
) { ) {
NavigationBar { NavigationBar {
items.forEach { item -> items.forEach { item ->
val selected = item.key == selectedKey
NavigationBarItem( NavigationBarItem(
selected = item.key == selectedKey, selected = selected,
onClick = { onItemClick(item) }, onClick = { onItemClick(item) },
icon = { icon = {
Icon( Icon(
painter = item.icon, imageVector = item.icon,
contentDescription = item.label contentDescription = item.label,
tint = if (selected)
MaterialTheme.colorScheme.primary
else
MaterialTheme.colorScheme.onSurfaceVariant
) )
}, },
label = { label = { Text(item.label) }
Text(text = item.label)
},
alwaysShowLabel = true
) )
} }
} }

View File

@@ -9,7 +9,7 @@ import java.util.Locale
class NewsHtmlParser { class NewsHtmlParser {
private val dateFormatter = private val dateFormatter =
DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale("ru")) DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale.forLanguageTag("ru"))
fun parseArchivePage(html: String): List<NewsItem> { fun parseArchivePage(html: String): List<NewsItem> {
val itemRegex = Regex( val itemRegex = Regex(

View File

@@ -3,7 +3,7 @@ package ru.fincode.tsudesk.feature.schedule.data.remote
object ScheduleApiContract { object ScheduleApiContract {
object Path { object Path {
const val GET_SCHEDULE_METHOD = "GetSchedule.php" const val GET_SCHEDULE_METHOD = "schedule/queries/GetSchedule.php"
} }
object Query { object Query {

View File

@@ -1,18 +1,25 @@
package ru.fincode.tsudesk.feature.schedule.presentation.navigation package ru.fincode.tsudesk.feature.schedule.presentation.navigation
import androidx.compose.ui.Modifier
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import ru.fincode.tsudesk.core.navigation.AppRoute import ru.fincode.tsudesk.core.navigation.AppRoute
import ru.fincode.tsudesk.feature.schedule.presentation.screen.ScheduleRoute import ru.fincode.tsudesk.feature.schedule.presentation.screen.ScheduleRoute
fun NavGraphBuilder.scheduleGraph( fun NavGraphBuilder.scheduleGraph(
modifier: Modifier = Modifier,
// на будущее:
// onOpenDetails: (lessonId: Long) -> Unit,
) { ) {
composable<AppRoute.Schedule> { composable<AppRoute.Schedule> {
ScheduleRoute() ScheduleRoute(
modifier = modifier,
// onOpenDetails = onOpenDetails
)
} }
// composable<AppRoute.ScheduleDetails> { backStackEntry -> // composable<AppRoute.ScheduleDetails> { entry ->
// val args = backStackEntry.toRoute<AppRoute.ScheduleDetails>() // val args = entry.toRoute<AppRoute.ScheduleDetails>()
// ScheduleDetailsRoute(lessonId = args.lessonId) // ScheduleDetailsRoute(lessonId = args.lessonId)
// } // }
} }

View File

@@ -1,4 +1,4 @@
package ru.fincode.tsudesk.feature.schedule.presentation package ru.fincode.tsudesk.feature.schedule.presentation.screen
sealed interface ScheduleAction { sealed interface ScheduleAction {