Skip to content

Commit aad8323

Browse files
committed
Add screens for: People, Random, Recent and Seasonal
1 parent 1ee6e48 commit aad8323

22 files changed

+362
-167
lines changed

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ android {
3030
applicationId "nl.giejay.android.tv.immich"
3131
minSdkVersion 24
3232
targetSdkVersion 35
33-
versionCode 62
34-
versionName "1.42"
33+
versionCode 64
34+
versionName "1.44"
3535

3636
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
3737
testOptions.unitTests.includeAndroidResources = true

app/src/main/java/nl/giejay/android/tv/immich/album/AlbumDetailsFragment.kt

Lines changed: 6 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,25 @@ import android.os.Bundle
44
import android.view.View
55
import androidx.navigation.fragment.findNavController
66
import arrow.core.Either
7-
import com.zeuskartik.mediaslider.DisplayOptions
8-
import com.zeuskartik.mediaslider.MediaSliderConfiguration
97
import nl.giejay.android.tv.immich.api.ApiClient
108
import nl.giejay.android.tv.immich.api.model.AlbumDetails
119
import nl.giejay.android.tv.immich.api.model.Asset
12-
import nl.giejay.android.tv.immich.api.util.ApiUtil
10+
import nl.giejay.android.tv.immich.assets.GenericAssetFragment
1311
import nl.giejay.android.tv.immich.card.Card
1412
import nl.giejay.android.tv.immich.home.HomeFragmentDirections
15-
import nl.giejay.android.tv.immich.shared.db.LocalStorage
16-
import nl.giejay.android.tv.immich.shared.fragment.VerticalCardGridFragment
1713
import nl.giejay.android.tv.immich.shared.prefs.LivePreference
1814
import nl.giejay.android.tv.immich.shared.prefs.LiveSharedPreferences
1915
import nl.giejay.android.tv.immich.shared.prefs.PreferenceManager
20-
import nl.giejay.android.tv.immich.shared.util.toCard
21-
import nl.giejay.android.tv.immich.shared.util.toSliderItems
22-
import java.util.EnumSet
2316

2417

25-
class AlbumDetailsFragment : VerticalCardGridFragment<Asset>() {
26-
private var currentAlbum: AlbumDetails? = null
18+
class AlbumDetailsFragment : GenericAssetFragment() {
2719
private lateinit var albumId: String
20+
private lateinit var albumName: String
2821
private lateinit var livePref: LivePreference<String>
2922

3023
override fun onCreate(savedInstanceState: Bundle?) {
3124
albumId = AlbumDetailsFragmentArgs.fromBundle(requireArguments()).albumId
25+
albumName = AlbumDetailsFragmentArgs.fromBundle(requireArguments()).albumName
3226
super.onCreate(savedInstanceState)
3327
livePref = LiveSharedPreferences(PreferenceManager.sharedPreference)
3428
.getString(PreferenceManager.keyAlbumsSorting(albumId), PreferenceManager.photosOrder().toString(), true)
@@ -49,7 +43,6 @@ class AlbumDetailsFragment : VerticalCardGridFragment<Asset>() {
4943
if(page == startPage){
5044
// no pagination possible yet!
5145
return apiClient.listAssetsFromAlbum(albumId).map {
52-
currentAlbum = it
5346
it.assets
5447
}
5548
}
@@ -62,48 +55,11 @@ class AlbumDetailsFragment : VerticalCardGridFragment<Asset>() {
6255

6356
override fun openPopUpMenu() {
6457
findNavController().navigate(
65-
HomeFragmentDirections.actionGlobalToSettingsDialog("album_details", albumId, currentAlbum!!.albumName)
58+
HomeFragmentDirections.actionGlobalToSettingsDialog("album_details", albumId, albumName)
6659
)
6760
}
6861

69-
override fun onItemClicked(card: Card) {
70-
// todo find a better way to pass data to other fragment without using the Intent extras (possibly too large)
71-
val displayOptions: EnumSet<DisplayOptions> = EnumSet.noneOf(DisplayOptions::class.java);
72-
if (PreferenceManager.sliderShowDescription()) {
73-
displayOptions += DisplayOptions.TITLE
74-
}
75-
if (PreferenceManager.sliderShowMediaCount()) {
76-
displayOptions += DisplayOptions.MEDIA_COUNT
77-
}
78-
if (PreferenceManager.sliderShowDate()) {
79-
displayOptions += DisplayOptions.DATE
80-
}
81-
LocalStorage.mediaSliderItems = assets.toSliderItems()
82-
findNavController().navigate(
83-
AlbumDetailsFragmentDirections.actionDetailsToPhotoSlider(
84-
MediaSliderConfiguration(
85-
displayOptions,
86-
currentAlbum!!.albumName,
87-
"",
88-
"",
89-
adapter.indexOf(card),
90-
PreferenceManager.sliderInterval(),
91-
PreferenceManager.sliderOnlyUseThumbnails(),
92-
true
93-
)
94-
)
95-
)
96-
}
97-
98-
override fun getBackgroundPicture(it: Asset): String? {
99-
return ApiUtil.getFileUrl(it.id)
100-
}
101-
10262
override fun setTitle(response: List<Asset>) {
103-
title = currentAlbum?.albumName
104-
}
105-
106-
override fun createCard(a: Asset): Card {
107-
return a.toCard()
63+
title = albumName
10864
}
10965
}

app/src/main/java/nl/giejay/android/tv/immich/album/AlbumFragment.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class AlbumFragment : VerticalCardGridFragment<Album>() {
5959
override fun onItemClicked(card: Card) {
6060
findNavController().navigate(
6161
HomeFragmentDirections.actionHomeFragmentToAlbumDetailsFragment(
62-
card.id
62+
card.id,
63+
card.title
6364
)
6465
)
6566
}

app/src/main/java/nl/giejay/android/tv/immich/api/ApiClient.kt

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package nl.giejay.android.tv.immich.api
22

33
import arrow.core.Either
44
import arrow.core.flatMap
5+
import arrow.core.getOrElse
56
import nl.giejay.android.tv.immich.api.model.Album
67
import nl.giejay.android.tv.immich.api.model.AlbumDetails
78
import nl.giejay.android.tv.immich.api.model.Asset
9+
import nl.giejay.android.tv.immich.api.model.Person
810
import nl.giejay.android.tv.immich.api.model.SearchRequest
911
import nl.giejay.android.tv.immich.api.service.ApiService
1012
import nl.giejay.android.tv.immich.api.util.ApiUtil.executeAPICall
@@ -13,6 +15,7 @@ import retrofit2.Retrofit
1315
import retrofit2.converter.gson.GsonConverterFactory
1416
import java.time.LocalDateTime
1517
import java.time.format.DateTimeFormatter
18+
import java.util.UUID
1619

1720
data class ApiClientConfig(
1821
val hostName: String,
@@ -50,6 +53,10 @@ class ApiClient(private val config: ApiClientConfig) {
5053
}
5154
}
5255

56+
suspend fun listPeople(): Either<String, List<Person>> {
57+
return executeAPICall(200) { service.listPeople() }.map { response -> response.people }
58+
}
59+
5360
suspend fun listAssetsFromAlbum(albumId: String): Either<String, AlbumDetails> {
5461
return executeAPICall(200) {
5562
val response = service.listAssetsFromAlbum(albumId)
@@ -60,14 +67,42 @@ class ApiClient(private val config: ApiClientConfig) {
6067
}
6168
}
6269

70+
suspend fun recentAssets(page: Int, pageCount: Int, includeVideos: Boolean): Either<String, List<Asset>> {
71+
val now = LocalDateTime.now()
72+
return apiClient!!.listAssets(page, pageCount, true, "desc",
73+
includeVideos = includeVideos, fromDate = now.minusMonths(5), endDate = now)
74+
}
75+
76+
suspend fun similarAssets(page: Int, pageCount: Int,includeVideos: Boolean): Either<String, List<Asset>> {
77+
val now = LocalDateTime.now()
78+
val map: List<Either<String, List<Asset>>> = (1 until 10).toList().map {
79+
apiClient!!.listAssets(page,
80+
pageCount,
81+
true,
82+
"desc",
83+
includeVideos = includeVideos,
84+
fromDate = now.minusMonths(1).minusYears(it.toLong()),
85+
endDate = now.plusMonths(1).minusYears(it.toLong()))
86+
}
87+
if (map.all { it.isLeft() }) {
88+
return map.first()
89+
}
90+
return Either.Right(map.flatMap { it.getOrElse { emptyList() } }.shuffled())
91+
}
92+
6393
suspend fun listAssets(page: Int,
6494
pageCount: Int,
65-
random: Boolean,
66-
order: String,
95+
random: Boolean = false,
96+
order: String = "desc",
97+
personIds: List<UUID> = emptyList(),
6798
includeVideos: Boolean = true,
6899
fromDate: LocalDateTime? = null,
69100
endDate: LocalDateTime? = null): Either<String, List<Asset>> {
70-
val searchRequest = SearchRequest(page, pageCount, order, if (includeVideos) null else "IMAGE",
101+
val searchRequest = SearchRequest(page,
102+
pageCount,
103+
order,
104+
if (includeVideos) null else "IMAGE",
105+
personIds,
71106
endDate?.format(dateTimeFormatter),
72107
fromDate?.format(dateTimeFormatter))
73108
return if (random) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package nl.giejay.android.tv.immich.api.model
2+
3+
import java.util.UUID
4+
5+
data class Person(
6+
val name: String,
7+
val id: UUID,
8+
val thumbnailPath: String
9+
)
10+
11+
data class PeopleResponse(val total: Int,
12+
val hasNextPage: Boolean,
13+
val people: List<Person>)

app/src/main/java/nl/giejay/android/tv/immich/api/model/SearchRequest.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package nl.giejay.android.tv.immich.api.model
22

3+
import java.util.UUID
4+
35
data class SearchRequest(val page: Int = 0,
46
val size: Int = 100,
57
val order: String = "desc",
68
val type: String? = null,
9+
val personIds: List<UUID> = emptyList(),
710
val takenBefore: String? = null,
811
val takenAfter: String? = null,
912
val withExif: Boolean = true

app/src/main/java/nl/giejay/android/tv/immich/api/service/ApiService.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package nl.giejay.android.tv.immich.api.service
33
import nl.giejay.android.tv.immich.api.model.Album
44
import nl.giejay.android.tv.immich.api.model.AlbumDetails
55
import nl.giejay.android.tv.immich.api.model.Asset
6+
import nl.giejay.android.tv.immich.api.model.PeopleResponse
67
import nl.giejay.android.tv.immich.api.model.SearchRequest
78
import nl.giejay.android.tv.immich.api.model.SearchResponse
89
import retrofit2.Response
@@ -23,6 +24,9 @@ interface ApiService {
2324
@GET("albums")
2425
suspend fun listAlbums(@Query("shared") shared: Boolean = false): Response<List<Album>>
2526

27+
@GET("people")
28+
suspend fun listPeople(): Response<PeopleResponse>
29+
2630
@GET("albums/{albumId}")
2731
suspend fun listAssetsFromAlbum(@Path("albumId") albumId: String): Response<AlbumDetails>
2832
}

app/src/main/java/nl/giejay/android/tv/immich/api/util/ApiUtil.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import nl.giejay.android.tv.immich.shared.prefs.PreferenceManager.hostName
55
import retrofit2.HttpException
66
import retrofit2.Response
77
import timber.log.Timber
8+
import java.util.UUID
89

910
object ApiUtil {
1011

@@ -20,6 +21,10 @@ object ApiUtil {
2021
}
2122
}
2223

24+
fun getPersonThumbnail(personId: UUID): String {
25+
return "${hostName().lowercase()}/api/people/$personId/thumbnail"
26+
}
27+
2328
suspend fun <T> executeAPICall(expectedStatus: Int, handler: suspend () -> Response<T>): Either<String, T> {
2429
try {
2530
val res = handler()
Lines changed: 3 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,12 @@
11
package nl.giejay.android.tv.immich.assets
22

3-
import androidx.navigation.fragment.findNavController
43
import arrow.core.Either
5-
import com.zeuskartik.mediaslider.DisplayOptions
6-
import com.zeuskartik.mediaslider.MediaSliderConfiguration
74
import nl.giejay.android.tv.immich.api.ApiClient
8-
import nl.giejay.android.tv.immich.api.util.ApiUtil
95
import nl.giejay.android.tv.immich.api.model.Asset
10-
import nl.giejay.android.tv.immich.card.Card
11-
import nl.giejay.android.tv.immich.home.HomeFragmentDirections
12-
import nl.giejay.android.tv.immich.shared.db.LocalStorage
13-
import nl.giejay.android.tv.immich.shared.fragment.VerticalCardGridFragment
146
import nl.giejay.android.tv.immich.shared.prefs.PhotosOrder
157
import nl.giejay.android.tv.immich.shared.prefs.PreferenceManager
16-
import nl.giejay.android.tv.immich.shared.util.toCard
17-
import nl.giejay.android.tv.immich.shared.util.toSliderItems
18-
import java.util.EnumSet
198

20-
class AllAssetFragment : VerticalCardGridFragment<Asset>() {
21-
override fun sortItems(items: List<Asset>): List<Asset> {
22-
return items
23-
}
9+
class AllAssetFragment : GenericAssetFragment() {
2410

2511
override suspend fun loadItems(
2612
apiClient: ApiClient,
@@ -33,40 +19,7 @@ class AllAssetFragment : VerticalCardGridFragment<Asset>() {
3319
if (PreferenceManager.allAssetsOrder() == PhotosOrder.NEWEST_OLDEST) "desc" else "asc")
3420
}
3521

36-
override fun onItemSelected(card: Card, indexOf: Int) {
37-
// no use case yet
38-
}
39-
40-
override fun onItemClicked(card: Card) {
41-
val displayOptions: EnumSet<DisplayOptions> = EnumSet.noneOf(DisplayOptions::class.java);
42-
if (PreferenceManager.sliderShowDescription()) {
43-
displayOptions += DisplayOptions.TITLE
44-
}
45-
if (PreferenceManager.sliderShowMediaCount()) {
46-
displayOptions += DisplayOptions.MEDIA_COUNT
47-
}
48-
LocalStorage.mediaSliderItems = assets.toSliderItems()
49-
findNavController().navigate(
50-
HomeFragmentDirections.actionHomeFragmentToPhotoSlider(
51-
MediaSliderConfiguration(
52-
displayOptions,
53-
"",
54-
"",
55-
"",
56-
adapter.indexOf(card),
57-
PreferenceManager.sliderInterval(),
58-
PreferenceManager.sliderOnlyUseThumbnails(),
59-
true
60-
)
61-
)
62-
)
63-
}
64-
65-
override fun getBackgroundPicture(it: Asset): String? {
66-
return ApiUtil.getFileUrl(it.id)
67-
}
68-
69-
override fun createCard(a: Asset): Card {
70-
return a.toCard()
22+
override fun showMediaCount(): Boolean {
23+
return PreferenceManager.sliderShowMediaCount()
7124
}
7225
}

0 commit comments

Comments
 (0)