Move ImageLoader module into main module.

This commit is contained in:
tzugen 2021-06-07 00:22:29 +02:00
parent f8efb6d592
commit 9161f9dc99
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
25 changed files with 232 additions and 207 deletions

View File

@ -1,29 +0,0 @@
apply from: bootstrap.androidModule
android {
buildFeatures {
buildConfig = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
api project(':core:domain')
api project(':core:subsonic-api')
api(other.picasso) {
exclude group: "com.android.support"
}
testImplementation testing.kotlinJunit
testImplementation testing.mockito
testImplementation testing.mockitoInline
testImplementation testing.mockitoKotlin
testImplementation testing.kluent
testImplementation testing.robolectric
}

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.moire.ultrasonic.subsonic.loader.image">
</manifest>

View File

@ -1,5 +1,4 @@
include ':core:domain'
include ':core:subsonic-api'
include ':core:subsonic-api-image-loader'
include ':core:cache'
include ':ultrasonic'

View File

@ -70,9 +70,12 @@ tasks.withType(Test) {
dependencies {
implementation project(':core:domain')
implementation project(':core:subsonic-api')
implementation project(':core:subsonic-api-image-loader')
implementation project(':core:cache')
api(other.picasso) {
exclude group: "com.android.support"
}
implementation androidSupport.core
implementation androidSupport.support
implementation androidSupport.design
@ -103,8 +106,12 @@ dependencies {
testImplementation testing.junit
testRuntimeOnly testing.junitVintage
testImplementation testing.kotlinJunit
testImplementation testing.mockitoKotlin
testImplementation testing.kluent
testImplementation testing.mockito
testImplementation testing.mockitoInline
testImplementation testing.mockitoKotlin
testImplementation testing.robolectric
implementation other.dexter
implementation other.timber
}

View File

@ -108,7 +108,7 @@ public class NowPlayingFragment extends Fragment {
String title = song.getTitle();
String artist = song.getArtist();
imageLoader.getValue().getImageLoader().loadImage(nowPlayingAlbumArtImage, song, false, Util.getNotificationImageSize(getContext()), false, true);
imageLoader.getValue().getImageLoader().loadImage(nowPlayingAlbumArtImage, song, false, Util.getNotificationImageSize(getContext()));
nowPlayingTrack.setText(title);
nowPlayingArtist.setText(artist);

View File

@ -1306,7 +1306,7 @@ public class PlayerFragment extends Fragment implements GestureDetector.OnGestur
artistTextView.setText(currentSong.getArtist());
downloadTrackTextView.setText(trackFormat);
downloadTotalDurationTextView.setText(duration);
imageLoaderProvider.getValue().getImageLoader().loadImage(albumArtImageView, currentSong, true, 0, false, true);
imageLoaderProvider.getValue().getImageLoader().loadImage(albumArtImageView, currentSong, true, 0);
displaySongRating();
}
@ -1318,7 +1318,7 @@ public class PlayerFragment extends Fragment implements GestureDetector.OnGestur
artistTextView.setText(null);
downloadTrackTextView.setText(null);
downloadTotalDurationTextView.setText(null);
imageLoaderProvider.getValue().getImageLoader().loadImage(albumArtImageView, null, true, 0, false, true);
imageLoaderProvider.getValue().getImageLoader().loadImage(albumArtImageView, null, true, 0);
}
}

View File

@ -28,7 +28,7 @@ import org.moire.ultrasonic.data.ActiveServerProvider;
import org.moire.ultrasonic.domain.MusicDirectory;
import org.moire.ultrasonic.service.MusicService;
import org.moire.ultrasonic.service.MusicServiceFactory;
import org.moire.ultrasonic.util.ImageLoader;
import org.moire.ultrasonic.imageloader.ImageLoader;
import org.moire.ultrasonic.util.Util;
/**
@ -109,7 +109,7 @@ public class AlbumView extends UpdateView
public void setAlbum(final MusicDirectory.Entry album)
{
viewHolder.cover_art.setTag(album);
imageLoader.loadImage(viewHolder.cover_art, album, false, 0, false, true);
imageLoader.loadImage(viewHolder.cover_art, album, false, 0);
this.entry = album;
String title = album.getTitle();

View File

@ -1,6 +1,7 @@
package org.moire.ultrasonic.view;
import android.content.Context;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
import android.view.LayoutInflater;
@ -12,8 +13,8 @@ import android.widget.TextView;
import org.moire.ultrasonic.R;
import org.moire.ultrasonic.data.ActiveServerProvider;
import org.moire.ultrasonic.domain.ChatMessage;
import org.moire.ultrasonic.imageloader.ImageLoader;
import org.moire.ultrasonic.subsonic.ImageLoaderProvider;
import org.moire.ultrasonic.util.ImageLoader;
import java.text.DateFormat;
import java.util.Date;
@ -33,7 +34,7 @@ public class ChatAdapter extends ArrayAdapter<ChatMessage>
private static final Pattern phoneMatcher = Pattern.compile(phoneRegex);
private final Lazy<ActiveServerProvider> activeServerProvider = inject(ActiveServerProvider.class);
private final Lazy<ImageLoaderProvider> imageLoader = inject(ImageLoaderProvider.class);
private final Lazy<ImageLoaderProvider> imageLoaderProvider = inject(ImageLoaderProvider.class);
public ChatAdapter(Context context, List<ChatMessage> messages)
{
@ -95,11 +96,11 @@ public class ChatAdapter extends ArrayAdapter<ChatMessage>
DateFormat timeFormat = android.text.format.DateFormat.getTimeFormat(context);
String messageTimeFormatted = String.format("[%s]", timeFormat.format(messageTime));
ImageLoader imageLoaderInstance = imageLoader.getValue().getImageLoader();
ImageLoader imageLoader = imageLoaderProvider.getValue().getImageLoader();
if (imageLoaderInstance != null)
if (holder.avatar != null && !TextUtils.isEmpty(messageUser))
{
imageLoaderInstance.loadAvatarImage(holder.avatar, messageUser, false, holder.avatar.getWidth(), false, true);
imageLoader.loadAvatarImage(holder.avatar, messageUser);
}
holder.username.setText(messageUser);

View File

@ -28,7 +28,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import org.moire.ultrasonic.domain.MusicDirectory.Entry;
import org.moire.ultrasonic.util.ImageLoader;
import org.moire.ultrasonic.imageloader.ImageLoader;
import java.util.List;

View File

@ -22,7 +22,7 @@ import org.moire.ultrasonic.subsonic.DownloadHandler
import org.moire.ultrasonic.subsonic.NetworkAndStorageChecker
import org.moire.ultrasonic.subsonic.ShareHandler
import org.moire.ultrasonic.subsonic.VideoPlayer
import org.moire.ultrasonic.subsonic.loader.image.SubsonicImageLoader
import org.moire.ultrasonic.imageloader.SubsonicImageLoader
import org.moire.ultrasonic.util.Constants
/**
@ -77,8 +77,6 @@ val musicServiceModule = module {
OfflineMusicService()
}
single { SubsonicImageLoader(androidContext(), get()) }
single { DownloadHandler(get(), get()) }
single { NetworkAndStorageChecker(androidContext()) }
single { VideoPlayer() }

View File

@ -15,7 +15,7 @@ import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import org.moire.ultrasonic.R
import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.util.ImageLoader
import org.moire.ultrasonic.imageloader.ImageLoader
/**
* Creates a Row in a RecyclerView which contains the details of an Album
@ -57,7 +57,7 @@ class AlbumRowAdapter(
imageLoader.loadImage(
holder.coverArt,
MusicDirectory.Entry("-1").apply { coverArt = holder.coverArtId },
false, 0, false, true, R.drawable.unknown_album
false, 0, R.drawable.unknown_album
)
}
}

View File

@ -15,7 +15,7 @@ import java.text.Collator
import org.moire.ultrasonic.R
import org.moire.ultrasonic.domain.Artist
import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.util.ImageLoader
import org.moire.ultrasonic.imageloader.ImageLoader
import org.moire.ultrasonic.util.Util
/**
@ -62,7 +62,7 @@ class ArtistRowAdapter(
imageLoader.loadImage(
holder.coverArt,
MusicDirectory.Entry("-1").apply { coverArt = holder.coverArtId },
false, 0, false, true, R.drawable.ic_contact_picture
false, 0, R.drawable.ic_contact_picture
)
} else {
holder.coverArt.visibility = View.GONE

View File

@ -763,7 +763,7 @@ class TrackCollectionFragment : Fragment() {
val artworkSelection = random.nextInt(entries.size)
imageLoaderProvider.getImageLoader().loadImage(
coverArtView, entries[artworkSelection], false,
Util.getAlbumImageSize(context), false, true
Util.getAlbumImageSize(context)
)
val albumHeader = AlbumHeader.processEntries(context, entries)

View File

@ -1,4 +1,4 @@
package org.moire.ultrasonic.subsonic.loader.image
package org.moire.ultrasonic.imageloader
import com.squareup.picasso.Picasso
import com.squareup.picasso.Request
@ -15,9 +15,7 @@ class AvatarRequestHandler(
) : RequestHandler() {
override fun canHandleRequest(data: Request): Boolean {
return with(data.uri) {
scheme == SCHEME &&
authority == AUTHORITY &&
path == "/$AVATAR_PATH"
scheme == SCHEME && path == "/$AVATAR_PATH"
}
}

View File

@ -1,4 +1,4 @@
package org.moire.ultrasonic.subsonic.loader.image
package org.moire.ultrasonic.imageloader
import com.squareup.picasso.Picasso.LoadedFrom.NETWORK
import com.squareup.picasso.Request
@ -14,7 +14,6 @@ class CoverArtRequestHandler(private val apiClient: SubsonicAPIClient) : Request
override fun canHandleRequest(data: Request): Boolean {
return with(data.uri) {
scheme == SCHEME &&
authority == AUTHORITY &&
path == "/$COVER_ART_PATH"
}
}

View File

@ -0,0 +1,157 @@
package org.moire.ultrasonic.imageloader
import android.content.Context
import android.view.View
import android.widget.ImageView
import com.squareup.picasso.Picasso
import com.squareup.picasso.RequestCreator
import org.moire.ultrasonic.BuildConfig
import org.moire.ultrasonic.R
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
import org.moire.ultrasonic.domain.MusicDirectory
import java.io.File
/**
* Our new image loader which uses Picasso as a backend.
*/
class ImageLoader(
context: Context,
apiClient: SubsonicAPIClient,
private val config: ImageLoaderConfig
) {
private val picasso = Picasso.Builder(context)
.addRequestHandler(CoverArtRequestHandler(apiClient))
.addRequestHandler(AvatarRequestHandler(apiClient))
.build().apply {
setIndicatorsEnabled(BuildConfig.DEBUG)
Picasso.setSingletonInstance(this)
}
private fun load(request: ImageRequest) = when (request) {
is ImageRequest.CoverArt -> loadCoverArt(request)
is ImageRequest.Avatar -> loadAvatar(request)
}
private fun loadCoverArt(request: ImageRequest.CoverArt) {
picasso.load(createLoadCoverArtRequest(request.entityId, request.size.toLong()))
.addPlaceholder(request)
.addError(request)
.stableKey("${request.entityId}-${request.size}")
.into(request.imageView)
}
private fun loadAvatar(request: ImageRequest.Avatar) {
picasso.load(createLoadAvatarRequest(request.username))
.addPlaceholder(request)
.addError(request)
.stableKey(request.username)
.into(request.imageView)
}
private fun RequestCreator.addPlaceholder(request: ImageRequest): RequestCreator {
if (request.placeHolderDrawableRes != null) {
placeholder(request.placeHolderDrawableRes)
}
return this
}
private fun RequestCreator.addError(request: ImageRequest): RequestCreator {
if (request.errorDrawableRes != null) {
error(request.errorDrawableRes)
}
return this
}
/**
* Load the cover of a given entry into an ImageView
*/
@JvmOverloads
fun loadImage(
view: View?,
entry: MusicDirectory.Entry?,
large: Boolean,
size: Int,
defaultResourceId: Int = R.drawable.unknown_album
) {
val id = entry?.coverArt
val requestedSize = resolveSize(size, large)
if (id != null && id.isNotEmpty() && view is ImageView) {
val request = ImageRequest.CoverArt(
id, view, requestedSize,
placeHolderDrawableRes = defaultResourceId,
errorDrawableRes = defaultResourceId
)
load(request)
}
}
/**
* Load the avatar of a given user into an ImageView
*/
fun loadAvatarImage(
view: ImageView,
username: String
) {
if (username.isNotEmpty()) {
val request = ImageRequest.Avatar(
username, view,
placeHolderDrawableRes = R.drawable.ic_contact_picture,
errorDrawableRes = R.drawable.ic_contact_picture
)
load(request)
}
}
private fun resolveSize(requested: Int, large: Boolean): Int {
if (requested <= 0) {
return if (large) config.largeSize else config.defaultSize
} else {
return requested
}
}
}
/**
* Data classes to hold all the info we need later on to process the request
*/
sealed class ImageRequest(
val placeHolderDrawableRes: Int? = null,
val errorDrawableRes: Int? = null,
val imageView: ImageView
) {
class CoverArt(
val entityId: String,
imageView: ImageView,
val size: Int,
placeHolderDrawableRes: Int? = null,
errorDrawableRes: Int? = null,
) : ImageRequest(
placeHolderDrawableRes,
errorDrawableRes,
imageView
)
class Avatar(
val username: String,
imageView: ImageView,
placeHolderDrawableRes: Int? = null,
errorDrawableRes: Int? = null
) : ImageRequest(
placeHolderDrawableRes,
errorDrawableRes,
imageView
)
}
/**
* Used to configure an instance of the ImageLoader
*/
data class ImageLoaderConfig (
val largeSize: Int = 0,
val defaultSize: Int = 0,
val cacheFolder: File?
)

View File

@ -1,9 +1,8 @@
package org.moire.ultrasonic.subsonic.loader.image
package org.moire.ultrasonic.imageloader
import android.net.Uri
internal const val SCHEME = "subsonic_api"
internal const val AUTHORITY = BuildConfig.LIBRARY_PACKAGE_NAME
internal const val COVER_ART_PATH = "cover_art"
internal const val AVATAR_PATH = "avatar"
internal const val QUERY_ID = "id"
@ -17,7 +16,6 @@ internal const val QUERY_USERNAME = "username"
internal fun createLoadCoverArtRequest(entityId: String, size: Long? = 0): Uri =
Uri.Builder()
.scheme(SCHEME)
.authority(AUTHORITY)
.appendPath(COVER_ART_PATH)
.appendQueryParameter(QUERY_ID, entityId)
.appendQueryParameter(SIZE, size.toString())
@ -26,7 +24,6 @@ internal fun createLoadCoverArtRequest(entityId: String, size: Long? = 0): Uri =
internal fun createLoadAvatarRequest(username: String): Uri =
Uri.Builder()
.scheme(SCHEME)
.authority(AUTHORITY)
.appendPath(AVATAR_PATH)
.appendQueryParameter(QUERY_USERNAME, username)
.build()

View File

@ -1,12 +1,11 @@
package org.moire.ultrasonic.subsonic.loader.image
package org.moire.ultrasonic.imageloader
import android.content.Context
import android.widget.ImageView
import com.squareup.picasso.Picasso
import com.squareup.picasso.RequestCreator
import org.moire.ultrasonic.BuildConfig
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
// TODO: Implement OkHTTP disk caching
class SubsonicImageLoader(
context: Context,
apiClient: SubsonicAPIClient
@ -56,32 +55,3 @@ class SubsonicImageLoader(
return this
}
}
sealed class ImageRequest(
val placeHolderDrawableRes: Int? = null,
val errorDrawableRes: Int? = null,
val imageView: ImageView
) {
class CoverArt(
val entityId: String,
imageView: ImageView,
val size: Int,
placeHolderDrawableRes: Int? = null,
errorDrawableRes: Int? = null,
) : ImageRequest(
placeHolderDrawableRes,
errorDrawableRes,
imageView
)
class Avatar(
val username: String,
imageView: ImageView,
placeHolderDrawableRes: Int? = null,
errorDrawableRes: Int? = null
) : ImageRequest(
placeHolderDrawableRes,
errorDrawableRes,
imageView
)
}

View File

@ -1,9 +1,15 @@
package org.moire.ultrasonic.subsonic
import android.content.Context
import androidx.core.content.res.ResourcesCompat
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
import org.moire.ultrasonic.util.ImageLoader
import org.moire.ultrasonic.R
import org.moire.ultrasonic.app.UApp
import org.moire.ultrasonic.util.FileUtil
import org.moire.ultrasonic.imageloader.ImageLoader
import org.moire.ultrasonic.imageloader.ImageLoaderConfig
import org.moire.ultrasonic.util.Util
/**
* Handles the lifetime of the Image Loader
@ -11,6 +17,26 @@ import org.moire.ultrasonic.util.ImageLoader
class ImageLoaderProvider(val context: Context) : KoinComponent {
private var imageLoader: ImageLoader? = null
private val config by lazy {
var defaultSize = 0
val fallbackImage = ResourcesCompat.getDrawable(
UApp.applicationContext().resources, R.drawable.unknown_album, null
)
// Determine the density-dependent image sizes by taking the fallback album
// image and querying its size.
if (fallbackImage != null) {
defaultSize = fallbackImage.intrinsicHeight
}
ImageLoaderConfig(
Util.getMaxDisplayMetric(),
defaultSize,
FileUtil.getAlbumArtDirectory()
)
}
@Synchronized
fun clearImageLoader() {
imageLoader = null
@ -19,7 +45,7 @@ class ImageLoaderProvider(val context: Context) : KoinComponent {
@Synchronized
fun getImageLoader(): ImageLoader {
if (imageLoader == null) {
imageLoader = SubsonicImageLoaderProxy(get())
imageLoader = ImageLoader(get(), get(), config)
}
return imageLoader!!
}

View File

@ -1,96 +0,0 @@
package org.moire.ultrasonic.subsonic
import android.view.View
import android.widget.ImageView
import androidx.core.content.res.ResourcesCompat
import org.moire.ultrasonic.R
import org.moire.ultrasonic.app.UApp
import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.subsonic.loader.image.ImageRequest
import org.moire.ultrasonic.subsonic.loader.image.SubsonicImageLoader
import org.moire.ultrasonic.util.ImageLoader
import org.moire.ultrasonic.util.Util
/**
* Proxy between [SubsonicImageLoader] and the main App.
* Needed to calculate values like the maximum image size,
* which we can't outside the main package.
*/
class SubsonicImageLoaderProxy(
private val subsonicImageLoader: SubsonicImageLoader
) : ImageLoader {
private var imageSizeLarge = Util.getMaxDisplayMetric()
private var imageSizeDefault = 0
override fun loadImage(
view: View?,
entry: MusicDirectory.Entry?,
large: Boolean,
size: Int,
crossFade: Boolean,
highQuality: Boolean
) {
return loadImage(view, entry, large, size, crossFade, highQuality, -1)
}
override fun loadImage(
view: View?,
entry: MusicDirectory.Entry?,
large: Boolean,
size: Int,
crossFade: Boolean,
highQuality: Boolean,
defaultResourceId: Int
) {
val id = entry?.coverArt
var requestedSize = size
val unknownImageId =
if (defaultResourceId == -1) R.drawable.unknown_album
else defaultResourceId
if (requestedSize <= 0) {
requestedSize = if (large) imageSizeLarge else imageSizeDefault
}
if (id != null && id.isNotEmpty() && view is ImageView) {
val request = ImageRequest.CoverArt(
id, view, requestedSize,
placeHolderDrawableRes = unknownImageId,
errorDrawableRes = unknownImageId
)
subsonicImageLoader.load(request)
}
}
override fun loadAvatarImage(
view: View?,
username: String?,
large: Boolean,
size: Int,
crossFade: Boolean,
highQuality: Boolean
) {
if (username != null && username.isNotEmpty() && view is ImageView) {
val request = ImageRequest.Avatar(
username, view,
placeHolderDrawableRes = R.drawable.ic_contact_picture,
errorDrawableRes = R.drawable.ic_contact_picture
)
subsonicImageLoader.load(request)
}
}
init {
val default = ResourcesCompat.getDrawable(
UApp.applicationContext().resources, R.drawable.unknown_album, null
)
// Determine the density-dependent image sizes by taking the fallback album
// image and querying its size.
if (default != null) {
imageSizeDefault = default.intrinsicHeight
}
}
}

View File

@ -1,4 +1,4 @@
package org.moire.ultrasonic.subsonic.loader.image
package org.moire.ultrasonic.imageloader
import android.net.Uri
import com.nhaarman.mockito_kotlin.any
@ -21,7 +21,8 @@ import org.robolectric.annotation.Config
@Config(manifest = Config.NONE)
class AvatarRequestHandlerTest {
private val mockSubsonicApiClient = mock<SubsonicAPIClient>()
private val handler = AvatarRequestHandler(mockSubsonicApiClient)
private val handler =
AvatarRequestHandler(mockSubsonicApiClient)
@Test
fun `Should accept only cover art request`() {
@ -34,7 +35,6 @@ class AvatarRequestHandlerTest {
fun `Should not accept random request uri`() {
val requestUri = Uri.Builder()
.scheme(SCHEME)
.authority(AUTHORITY)
.appendPath("something")
.build()
@ -63,7 +63,8 @@ class AvatarRequestHandlerTest {
whenever(mockSubsonicApiClient.getAvatar(any()))
.thenReturn(streamResponse)
val response = handler.load(createLoadAvatarRequest("some-username").buildRequest(), 0)
val response = handler.load(
createLoadAvatarRequest("some-username").buildRequest(), 0)
response.loadedFrom `should be equal to` Picasso.LoadedFrom.NETWORK
response.source `should not be` null

View File

@ -1,4 +1,4 @@
package org.moire.ultrasonic.subsonic.loader.image
package org.moire.ultrasonic.imageloader
import java.io.InputStream
import okio.Okio

View File

@ -1,4 +1,4 @@
package org.moire.ultrasonic.subsonic.loader.image
package org.moire.ultrasonic.imageloader
import android.net.Uri
import com.nhaarman.mockito_kotlin.any
@ -21,7 +21,8 @@ import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class CoverArtRequestHandlerTest {
private val mockSubsonicApiClientMock = mock<SubsonicAPIClient>()
private val handler = CoverArtRequestHandler(mockSubsonicApiClientMock)
private val handler =
CoverArtRequestHandler(mockSubsonicApiClientMock)
@Test
fun `Should accept only cover art request`() {
@ -34,7 +35,6 @@ class CoverArtRequestHandlerTest {
fun `Should not accept random request uri`() {
val requestUri = Uri.Builder()
.scheme(SCHEME)
.authority(AUTHORITY)
.appendPath("random")
.build()
@ -76,7 +76,8 @@ class CoverArtRequestHandlerTest {
whenever(mockSubsonicApiClientMock.getCoverArt(any(), anyOrNull()))
.thenReturn(streamResponse)
val response = handler.load(createLoadCoverArtRequest("some").buildRequest(), 0)
val response = handler.load(
createLoadCoverArtRequest("some").buildRequest(), 0)
response.loadedFrom `should be equal to` Picasso.LoadedFrom.NETWORK
response.source `should not be` null

View File

@ -1,4 +1,4 @@
package org.moire.ultrasonic.subsonic.loader.image
package org.moire.ultrasonic.imageloader
import android.net.Uri
import org.amshove.kluent.shouldBeEqualTo
@ -13,7 +13,7 @@ class RequestCreatorTest {
val entityId = "299"
val size = 100L
val expectedUri =
Uri.parse("$SCHEME://$AUTHORITY/$COVER_ART_PATH?$QUERY_ID=$entityId&$SIZE=$size")
Uri.parse("$SCHEME:/$COVER_ART_PATH?$QUERY_ID=$entityId&$SIZE=$size")
createLoadCoverArtRequest(entityId, size).compareTo(expectedUri).shouldBeEqualTo(0)
}
@ -21,7 +21,7 @@ class RequestCreatorTest {
@Test
fun `Should create valid avatar request`() {
val username = "some-username"
val expectedUri = Uri.parse("$SCHEME://$AUTHORITY/$AVATAR_PATH?$QUERY_USERNAME=$username")
val expectedUri = Uri.parse("$SCHEME:/$AVATAR_PATH?$QUERY_USERNAME=$username")
createLoadAvatarRequest(username).compareTo(expectedUri).shouldBeEqualTo(0)
}

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB