Merge pull request #1 from hammsterr/feature-yandex-ads
Подключение РСЯ
This commit is contained in:
@@ -91,6 +91,10 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.room)
|
implementation(libs.room)
|
||||||
implementation("androidx.media3:media3-datasource-okhttp:1.0.0-alpha03")
|
implementation("androidx.media3:media3-datasource-okhttp:1.0.0-alpha03")
|
||||||
|
|
||||||
|
implementation ("com.yandex.android:mobileads:6.4.0")
|
||||||
|
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
|
||||||
|
|
||||||
kapt(libs.room.compiler)
|
kapt(libs.room.compiler)
|
||||||
|
|
||||||
implementation(projects.innertube)
|
implementation(projects.innertube)
|
||||||
|
|||||||
2
app/proguard-rules.pro
vendored
2
app/proguard-rules.pro
vendored
@@ -32,3 +32,5 @@
|
|||||||
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
|
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
|
||||||
-dontwarn org.openjsse.net.ssl.OpenJSSE
|
-dontwarn org.openjsse.net.ssl.OpenJSSE
|
||||||
-dontwarn org.slf4j.impl.StaticLoggerBinder
|
-dontwarn org.slf4j.impl.StaticLoggerBinder
|
||||||
|
|
||||||
|
-keep class com.yandex** { *; }
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||||
|
<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove"/>
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.app.Application
|
|||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.ImageLoaderFactory
|
import coil.ImageLoaderFactory
|
||||||
import coil.disk.DiskCache
|
import coil.disk.DiskCache
|
||||||
|
import com.yandex.mobile.ads.common.MobileAds
|
||||||
import it.hamy.muza.enums.CoilDiskCacheMaxSize
|
import it.hamy.muza.enums.CoilDiskCacheMaxSize
|
||||||
import it.hamy.muza.utils.coilDiskCacheMaxSizeKey
|
import it.hamy.muza.utils.coilDiskCacheMaxSizeKey
|
||||||
import it.hamy.muza.utils.getEnum
|
import it.hamy.muza.utils.getEnum
|
||||||
@@ -13,6 +14,11 @@ class MainApplication : Application(), ImageLoaderFactory {
|
|||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
DatabaseInitializer()
|
DatabaseInitializer()
|
||||||
|
MobileAds.initialize(this) {
|
||||||
|
/**
|
||||||
|
* Инициализация либы яндекса
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun newImageLoader(): ImageLoader {
|
override fun newImageLoader(): ImageLoader {
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package it.hamy.muza.ui.components
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
|
import com.yandex.mobile.ads.banner.BannerAdEventListener
|
||||||
|
import com.yandex.mobile.ads.banner.BannerAdSize
|
||||||
|
import com.yandex.mobile.ads.banner.BannerAdView
|
||||||
|
import com.yandex.mobile.ads.common.AdRequest
|
||||||
|
import com.yandex.mobile.ads.common.AdRequestError
|
||||||
|
import com.yandex.mobile.ads.common.ImpressionData
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun YandexAdsBanner(id: String) {
|
||||||
|
AndroidView(modifier = Modifier.fillMaxSize(), factory = { context ->
|
||||||
|
BannerAdView(context).apply {
|
||||||
|
/**
|
||||||
|
* ID блока рекламы
|
||||||
|
*/
|
||||||
|
setAdUnitId(id)
|
||||||
|
/**
|
||||||
|
* Размер блока рекламы
|
||||||
|
*/
|
||||||
|
setAdSize(BannerAdSize.inlineSize(context, 140, 60))
|
||||||
|
/**
|
||||||
|
* Билдер запроса
|
||||||
|
*/
|
||||||
|
val adRequest = AdRequest.Builder().build()
|
||||||
|
/**
|
||||||
|
* Слушатель экшнов
|
||||||
|
*/
|
||||||
|
setBannerAdEventListener(object : BannerAdEventListener {
|
||||||
|
override fun onAdLoaded() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAdFailedToLoad(p0: AdRequestError) {
|
||||||
|
/**
|
||||||
|
* Тут дебажим ошибки
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAdClicked() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLeftApplication() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onReturnedToApplication() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onImpression(p0: ImpressionData?) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Запуск баннера
|
||||||
|
*/
|
||||||
|
loadAd(adRequest)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -9,17 +9,22 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
import androidx.compose.foundation.layout.asPaddingValues
|
import androidx.compose.foundation.layout.asPaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.only
|
import androidx.compose.foundation.layout.only
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.GridItemSpan
|
import androidx.compose.foundation.lazy.grid.GridItemSpan
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
import androidx.compose.foundation.lazy.grid.items
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -40,6 +45,7 @@ import it.hamy.muza.enums.SortOrder
|
|||||||
import it.hamy.muza.models.Playlist
|
import it.hamy.muza.models.Playlist
|
||||||
import it.hamy.muza.models.PlaylistPreview
|
import it.hamy.muza.models.PlaylistPreview
|
||||||
import it.hamy.muza.query
|
import it.hamy.muza.query
|
||||||
|
import it.hamy.muza.ui.components.YandexAdsBanner
|
||||||
import it.hamy.muza.ui.components.themed.FloatingActionsContainerWithScrollToTop
|
import it.hamy.muza.ui.components.themed.FloatingActionsContainerWithScrollToTop
|
||||||
import it.hamy.muza.ui.components.themed.Header
|
import it.hamy.muza.ui.components.themed.Header
|
||||||
import it.hamy.muza.ui.components.themed.HeaderIconButton
|
import it.hamy.muza.ui.components.themed.HeaderIconButton
|
||||||
@@ -104,107 +110,122 @@ fun HomePlaylists(
|
|||||||
|
|
||||||
val lazyGridState = rememberLazyGridState()
|
val lazyGridState = rememberLazyGridState()
|
||||||
|
|
||||||
Box {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
LazyVerticalGrid(
|
Column(
|
||||||
state = lazyGridState,
|
|
||||||
columns = GridCells.Adaptive(Dimensions.thumbnails.song * 2 + Dimensions.itemsVerticalPadding * 2),
|
|
||||||
contentPadding = LocalPlayerAwareWindowInsets.current
|
|
||||||
.only(WindowInsetsSides.Vertical + WindowInsetsSides.End).asPaddingValues(),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(Dimensions.itemsVerticalPadding * 2),
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(
|
|
||||||
space = Dimensions.itemsVerticalPadding * 2,
|
|
||||||
alignment = Alignment.CenterHorizontally
|
|
||||||
),
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(colorPalette.background0)
|
|
||||||
) {
|
) {
|
||||||
item(key = "header", contentType = 0, span = { GridItemSpan(maxLineSpan) }) {
|
LazyVerticalGrid(
|
||||||
Header(title = "Плейлисты") {
|
state = lazyGridState,
|
||||||
SecondaryTextButton(
|
columns = GridCells.Adaptive(Dimensions.thumbnails.song * 2 + Dimensions.itemsVerticalPadding * 2),
|
||||||
text = "Новый плейлист",
|
contentPadding = LocalPlayerAwareWindowInsets.current
|
||||||
onClick = { isCreatingANewPlaylist = true }
|
.only(WindowInsetsSides.Vertical + WindowInsetsSides.End).asPaddingValues(),
|
||||||
)
|
verticalArrangement = Arrangement.spacedBy(Dimensions.itemsVerticalPadding * 2),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(
|
||||||
|
space = Dimensions.itemsVerticalPadding * 2,
|
||||||
|
alignment = Alignment.CenterHorizontally
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(colorPalette.background0)
|
||||||
|
) {
|
||||||
|
item(key = "header", contentType = 0, span = { GridItemSpan(maxLineSpan) }) {
|
||||||
|
Header(title = "Плейлисты") {
|
||||||
|
SecondaryTextButton(
|
||||||
|
text = "Новый плейлист",
|
||||||
|
onClick = { isCreatingANewPlaylist = true }
|
||||||
|
)
|
||||||
|
|
||||||
Spacer(
|
Spacer(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
|
HeaderIconButton(
|
||||||
|
icon = R.drawable.medical,
|
||||||
|
color = if (sortBy == PlaylistSortBy.SongCount) colorPalette.text else colorPalette.textDisabled,
|
||||||
|
onClick = { sortBy = PlaylistSortBy.SongCount }
|
||||||
|
)
|
||||||
|
|
||||||
|
HeaderIconButton(
|
||||||
|
icon = R.drawable.text,
|
||||||
|
color = if (sortBy == PlaylistSortBy.Name) colorPalette.text else colorPalette.textDisabled,
|
||||||
|
onClick = { sortBy = PlaylistSortBy.Name }
|
||||||
|
)
|
||||||
|
|
||||||
|
HeaderIconButton(
|
||||||
|
icon = R.drawable.time,
|
||||||
|
color = if (sortBy == PlaylistSortBy.DateAdded) colorPalette.text else colorPalette.textDisabled,
|
||||||
|
onClick = { sortBy = PlaylistSortBy.DateAdded }
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(2.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
HeaderIconButton(
|
||||||
|
icon = R.drawable.arrow_up,
|
||||||
|
color = colorPalette.text,
|
||||||
|
onClick = { sortOrder = !sortOrder },
|
||||||
|
modifier = Modifier
|
||||||
|
.graphicsLayer { rotationZ = sortOrderIconRotation }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item(key = "favorites") {
|
||||||
|
PlaylistItem(
|
||||||
|
icon = R.drawable.heart,
|
||||||
|
colorTint = colorPalette.red,
|
||||||
|
name = "Любимые",
|
||||||
|
songCount = null,
|
||||||
|
thumbnailSizeDp = thumbnailSizeDp,
|
||||||
|
alternative = true,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.clickable(onClick = { onBuiltInPlaylist(BuiltInPlaylist.Favorites) })
|
||||||
)
|
.animateItemPlacement()
|
||||||
|
|
||||||
HeaderIconButton(
|
|
||||||
icon = R.drawable.medical,
|
|
||||||
color = if (sortBy == PlaylistSortBy.SongCount) colorPalette.text else colorPalette.textDisabled,
|
|
||||||
onClick = { sortBy = PlaylistSortBy.SongCount }
|
|
||||||
)
|
|
||||||
|
|
||||||
HeaderIconButton(
|
|
||||||
icon = R.drawable.text,
|
|
||||||
color = if (sortBy == PlaylistSortBy.Name) colorPalette.text else colorPalette.textDisabled,
|
|
||||||
onClick = { sortBy = PlaylistSortBy.Name }
|
|
||||||
)
|
|
||||||
|
|
||||||
HeaderIconButton(
|
|
||||||
icon = R.drawable.time,
|
|
||||||
color = if (sortBy == PlaylistSortBy.DateAdded) colorPalette.text else colorPalette.textDisabled,
|
|
||||||
onClick = { sortBy = PlaylistSortBy.DateAdded }
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(
|
|
||||||
modifier = Modifier
|
|
||||||
.width(2.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
HeaderIconButton(
|
|
||||||
icon = R.drawable.arrow_up,
|
|
||||||
color = colorPalette.text,
|
|
||||||
onClick = { sortOrder = !sortOrder },
|
|
||||||
modifier = Modifier
|
|
||||||
.graphicsLayer { rotationZ = sortOrderIconRotation }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
item(key = "favorites") {
|
item(key = "offline") {
|
||||||
PlaylistItem(
|
PlaylistItem(
|
||||||
icon = R.drawable.heart,
|
icon = R.drawable.airplane,
|
||||||
colorTint = colorPalette.red,
|
colorTint = colorPalette.blue,
|
||||||
name = "Любимые",
|
name = "Сохранённые",
|
||||||
songCount = null,
|
songCount = null,
|
||||||
thumbnailSizeDp = thumbnailSizeDp,
|
thumbnailSizeDp = thumbnailSizeDp,
|
||||||
alternative = true,
|
alternative = true,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable(onClick = { onBuiltInPlaylist(BuiltInPlaylist.Favorites) })
|
.clickable(onClick = { onBuiltInPlaylist(BuiltInPlaylist.Offline) })
|
||||||
.animateItemPlacement()
|
.animateItemPlacement()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
item(key = "offline") {
|
items(items = items, key = { it.playlist.id }) { playlistPreview ->
|
||||||
PlaylistItem(
|
PlaylistItem(
|
||||||
icon = R.drawable.airplane,
|
playlist = playlistPreview,
|
||||||
colorTint = colorPalette.blue,
|
thumbnailSizeDp = thumbnailSizeDp,
|
||||||
name = "Сохранённые",
|
thumbnailSizePx = thumbnailSizePx,
|
||||||
songCount = null,
|
alternative = true,
|
||||||
thumbnailSizeDp = thumbnailSizeDp,
|
modifier = Modifier
|
||||||
alternative = true,
|
.clickable(onClick = { onPlaylistClick(playlistPreview.playlist) })
|
||||||
modifier = Modifier
|
.animateItemPlacement()
|
||||||
.clickable(onClick = { onBuiltInPlaylist(BuiltInPlaylist.Offline) })
|
)
|
||||||
.animateItemPlacement()
|
}
|
||||||
)
|
item {
|
||||||
}
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
items(items = items, key = { it.playlist.id }) { playlistPreview ->
|
.fillMaxSize()
|
||||||
PlaylistItem(
|
.padding(start = 14.dp, end = 10.dp, top = 30.dp)
|
||||||
playlist = playlistPreview,
|
.align(Alignment.CenterHorizontally),
|
||||||
thumbnailSizeDp = thumbnailSizeDp,
|
contentAlignment = Alignment.Center,
|
||||||
thumbnailSizePx = thumbnailSizePx,
|
) {
|
||||||
alternative = true,
|
YandexAdsBanner(id = "R-M-5961316-1")
|
||||||
modifier = Modifier
|
}
|
||||||
.clickable(onClick = { onPlaylistClick(playlistPreview.playlist) })
|
}
|
||||||
.animateItemPlacement()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingActionsContainerWithScrollToTop(
|
FloatingActionsContainerWithScrollToTop(
|
||||||
lazyGridState = lazyGridState,
|
lazyGridState = lazyGridState,
|
||||||
iconId = R.drawable.search,
|
iconId = R.drawable.search,
|
||||||
|
|||||||
Reference in New Issue
Block a user