Added opening hours and a button for the user to view them, but the formatting sucks

This commit is contained in:
denizk0461
2023-04-25 16:55:17 +02:00
parent 6b1d77dfb3
commit 65114264c4
13 changed files with 127 additions and 19 deletions
@@ -94,8 +94,23 @@ class StwParser {
// Parse the HTML using Jsoup to traverse the document // Parse the HTML using Jsoup to traverse the document
val doc = Jsoup.connect(url).get() val doc = Jsoup.connect(url).get()
/*
* Retrieve the opening hours for the canteen.
* TODO this formatting sucks
*/
var openingHours = ""
doc.getElementsByClass("details-wrapper")[0].getElementsByTag("p").forEach { p ->
openingHours += "${p.text()}\n"
}
// Save the canteen to persistent storage // Save the canteen to persistent storage
repo.insert(OfferCanteen(canteenId, doc.getElementsByClass("pane-title")[1].text())) repo.insert(
OfferCanteen(
canteenId,
doc.getElementsByClass("pane-title")[1].text(),
openingHours,
)
)
// Iterate through each day for which offers are available // Iterate through each day for which offers are available
doc.getElementsByClass("food-plan").forEach { dayPlan -> doc.getElementsByClass("food-plan").forEach { dayPlan ->
@@ -148,4 +148,12 @@ interface AppDAO {
* @param item object to be saved to the database * @param item object to be saved to the database
*/ */
@Insert fun insert(item: OfferItem) @Insert fun insert(item: OfferItem)
/**
* Retrieves the opening hours of the canteen as a string.
*
* @return opening hours
*/
@Query("SELECT openingHours FROM offer_canteen LIMIT 1")
fun getCanteenOpeningHours(): String
} }
@@ -17,7 +17,7 @@ import com.denizk0461.studip.model.*
OfferCategory::class, OfferCategory::class,
OfferItem::class OfferItem::class
], ],
version = 13, version = 14,
) )
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
@@ -44,6 +44,13 @@ class AppRepository(app: Application) {
*/ */
fun nukeEvents() { dao.nukeEvents() } fun nukeEvents() { dao.nukeEvents() }
/**
* Retrieves the opening hours of the canteen as a string.
*
* @return opening hours
*/
fun getCanteenOpeningHours() = dao.getCanteenOpeningHours()
/** /**
* Retrieves all canteen offers. * Retrieves all canteen offers.
* *
@@ -13,6 +13,7 @@ import com.denizk0461.studip.adapter.CanteenOfferPageAdapter
import com.denizk0461.studip.databinding.FragmentCanteenBinding import com.denizk0461.studip.databinding.FragmentCanteenBinding
import com.denizk0461.studip.model.* import com.denizk0461.studip.model.*
import com.denizk0461.studip.sheet.AllergenSheet import com.denizk0461.studip.sheet.AllergenSheet
import com.denizk0461.studip.sheet.TextSheet
import com.denizk0461.studip.viewmodel.CanteenViewModel import com.denizk0461.studip.viewmodel.CanteenViewModel
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
@@ -47,6 +48,8 @@ class CanteenFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListener {
// Used if no preference has been set or none can be found // Used if no preference has been set or none can be found
private val emptyPreferenceRegex: String = ".........." private val emptyPreferenceRegex: String = ".........."
private var openingHours = ""
// Instantiate the view binding // Instantiate the view binding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentCanteenBinding.inflate(inflater, container, false) _binding = FragmentCanteenBinding.inflate(inflater, container, false)
@@ -73,6 +76,9 @@ class CanteenFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListener {
R.id.mensa_hfk -> 9 R.id.mensa_hfk -> 9
else -> 0 else -> 0
} }
// Set currently selected canteen to the button
binding.buttonCanteenPicker.text = getCurrentlySelectedCanteenName()
refresh()
true true
} }
inflate(R.menu.menu_canteens) inflate(R.menu.menu_canteens)
@@ -80,6 +86,18 @@ class CanteenFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListener {
} }
} }
binding.buttonInfo.setOnClickListener {
openBottomSheet(
TextSheet(
getString(
R.string.canteen_opening_hours,
getCurrentlySelectedCanteenName()
),
openingHours
)
)
}
// Assign a preference value to every button to filter for dietary preferences // Assign a preference value to every button to filter for dietary preferences
val chipMap = mapOf( val chipMap = mapOf(
@@ -146,6 +164,9 @@ class CanteenFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListener {
// Update the item list in the view pager's adapter // Update the item list in the view pager's adapter
viewPagerAdapter.setNewItems(groupedElements, dateSize) viewPagerAdapter.setNewItems(groupedElements, dateSize)
// Set the text for the opening hours dialogue
openingHours = viewModel.getCanteenOpeningHours()
/* /*
* Tell the swipe refresh layout to stop refreshing. * Tell the swipe refresh layout to stop refreshing.
* TODO if an exception is raised, this will not be fired. This must be changed * TODO if an exception is raised, this will not be fired. This must be changed
@@ -155,14 +176,7 @@ class CanteenFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListener {
// Set up functions for when the user swipes to refresh the view // Set up functions for when the user swipes to refresh the view
binding.swipeRefreshLayout.setOnRefreshListener { binding.swipeRefreshLayout.setOnRefreshListener {
// Retrieve new offers from the website(s) refresh()
viewModel.fetchOffers(viewModel.preferenceCanteen, onRefreshUpdate = { status ->
// TODO refresh updates
}, onFinish = {
// createTabLayoutMediator()
// binding.swipeRefreshLayout.isRefreshing = false
// createTabLayoutMediator()
})
} }
} }
@@ -179,7 +193,6 @@ class CanteenFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListener {
TabLayoutMediator(binding.dayTabLayout, binding.viewPager) { tab, position -> TabLayoutMediator(binding.dayTabLayout, binding.viewPager) { tab, position ->
tab.text = dates[position].date tab.text = dates[position].date
}.attach() }.attach()
} }
} }
@@ -303,6 +316,41 @@ class CanteenFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListener {
} }
} }
/**
* Retrieves the localised string for the canteen selected by the user.
*
* @return the localised canteen name
*/
private fun getCurrentlySelectedCanteenName(): String = getString(
when (viewModel.preferenceCanteen) {
0 -> R.string.mensa_uni
1 -> R.string.cafe_central
2 -> R.string.mensa_nw1
3 -> R.string.cafeteria_gw2
4 -> R.string.mensa_neustadt
5 -> R.string.mensa_werder
6 -> R.string.mensa_airport
7 -> R.string.mensa_bhv
8 -> R.string.cafeteria_bhv
9 -> R.string.mensa_hfk
else -> R.string.mensa_uni
}
)
/**
* Downloads the canteen offers and refreshes them in the app.
*/
private fun refresh() {
// Retrieve new offers from the website(s)
viewModel.fetchOffers(viewModel.preferenceCanteen, onRefreshUpdate = { status ->
// TODO refresh updates
}, onFinish = {
// createTabLayoutMediator()
// binding.swipeRefreshLayout.isRefreshing = false
// createTabLayoutMediator()
})
}
/** /**
* Executed when an item has been clicked. * Executed when an item has been clicked.
* *
@@ -87,8 +87,8 @@ class SettingsFragment : AppFragment() {
// Set click listener for the data handling dialogue // Set click listener for the data handling dialogue
binding.buttonDataHandling.setOnClickListener { binding.buttonDataHandling.setOnClickListener {
openBottomSheet(TextSheet( openBottomSheet(TextSheet(
R.string.settings_data_sheet_header, getString(R.string.settings_data_sheet_header),
R.string.settings_data_sheet_content getString(R.string.settings_data_sheet_content),
)) ))
} }
@@ -6,8 +6,9 @@ import androidx.room.PrimaryKey
/** /**
* Entity for binding several canteen items to a specific date. Registered in the app database. * Entity for binding several canteen items to a specific date. Registered in the app database.
* *
* @param id primary key that uniquely identifies the item * @param id primary key that uniquely identifies the item
* @param canteen name of the canteen * @param canteen name of the canteen
* @param openingHours opening hours of the canteen
*/ */
@Entity( @Entity(
tableName = "offer_canteen", tableName = "offer_canteen",
@@ -15,4 +16,5 @@ import androidx.room.PrimaryKey
data class OfferCanteen( data class OfferCanteen(
@PrimaryKey val id: Int, @PrimaryKey val id: Int,
val canteen: String, val canteen: String,
val openingHours: String,
) )
@@ -14,8 +14,8 @@ import com.denizk0461.studip.databinding.SheetTextBinding
* @param content content text for the window * @param content content text for the window
*/ */
class TextSheet( class TextSheet(
@StringRes private val header: Int, private val header: String,
@StringRes private val content: Int private val content: String,
) : AppSheet(R.layout.sheet_text) { ) : AppSheet(R.layout.sheet_text) {
// View binding // View binding
@@ -26,8 +26,8 @@ class TextSheet(
// Set text values // Set text values
binding.apply { binding.apply {
textHeader.text = getString(header) textHeader.text = header
textContent.text = getString(content) textContent.text = content
} }
} }
} }
@@ -36,6 +36,13 @@ class CanteenViewModel(app: Application) : AppViewModel(app) {
*/ */
fun getDates(): List<OfferDate> = returnBlocking { repo.getDates() } fun getDates(): List<OfferDate> = returnBlocking { repo.getDates() }
/**
* Retrieves the opening hours of the canteen as a string.
*
* @return opening hours
*/
fun getCanteenOpeningHours(): String = returnBlocking { repo.getCanteenOpeningHours() }
// Fetch the canteen offers asynchronously. Updates will be provided through a LiveData object. // Fetch the canteen offers asynchronously. Updates will be provided through a LiveData object.
fun fetchOffers(canteen: Int, onRefreshUpdate: (status: Int) -> Unit, onFinish: () -> Unit) { fun fetchOffers(canteen: Int, onRefreshUpdate: (status: Int) -> Unit, onFinish: () -> Unit) {
doAsync { parser.parse(canteen, onRefreshUpdate, onFinish) } doAsync { parser.parse(canteen, onRefreshUpdate, onFinish) }
+5
View File
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
</vector>
@@ -42,6 +42,18 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/> app:layout_constraintStart_toStartOf="parent"/>
<com.google.android.material.button.MaterialButton
style="@style/Widget.Material3.Button.TextButton"
android:id="@+id/button_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="0dp"
app:icon="@drawable/info"
app:iconPadding="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:iconTint="?attr/colorOnSurfaceVariant"/>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout" android:id="@+id/swipe_refresh_layout"
android:layout_width="0dp" android:layout_width="0dp"
+2
View File
@@ -23,6 +23,8 @@
<string name="title_food">Mensenangebote</string> <string name="title_food">Mensenangebote</string>
<string name="title_settings">App-Einstellungen</string> <string name="title_settings">App-Einstellungen</string>
<string name="canteen_opening_hours">%s Öffnungszeiten</string>
<string name="mensa_uni">Uni-Mensa</string> <string name="mensa_uni">Uni-Mensa</string>
<string name="cafe_central">Café Central</string> <string name="cafe_central">Café Central</string>
<string name="mensa_nw1">Mensa NW1</string> <string name="mensa_nw1">Mensa NW1</string>
+2
View File
@@ -24,6 +24,8 @@
<string name="title_food">Canteen Offers</string> <string name="title_food">Canteen Offers</string>
<string name="title_settings">App Settings</string> <string name="title_settings">App Settings</string>
<string name="canteen_opening_hours">%s Opening Hours</string>
<string name="mensa_uni">Uni-Mensa</string> <string name="mensa_uni">Uni-Mensa</string>
<string name="cafe_central">Café Central</string> <string name="cafe_central">Café Central</string>
<string name="mensa_nw1">Mensa NW1</string> <string name="mensa_nw1">Mensa NW1</string>