Update Compose
This commit is contained in:
+7
-21
@@ -10,11 +10,11 @@ android {
|
|||||||
compileSdkVersion = 34
|
compileSdkVersion = 34
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.lsp.view"
|
applicationId "moe.uni.moe"
|
||||||
minSdkVersion 29
|
minSdkVersion 29
|
||||||
targetSdkVersion 34
|
targetSdkVersion 34
|
||||||
versionCode 221022
|
versionCode 240629
|
||||||
versionName "1.2.7"
|
versionName "2.0.0"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
@@ -27,12 +27,10 @@ android {
|
|||||||
debuggable true
|
debuggable true
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
shrinkResources false
|
shrinkResources false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@@ -42,7 +40,7 @@ android {
|
|||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '1.8'
|
jvmTarget = '1.8'
|
||||||
}
|
}
|
||||||
namespace 'com.lsp.view'
|
namespace 'moe.uni.view'
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose true
|
compose true
|
||||||
}
|
}
|
||||||
@@ -58,7 +56,6 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.navigation:navigation-compose:2.7.7")
|
implementation("androidx.navigation:navigation-compose:2.7.7")
|
||||||
|
|
||||||
implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
|
implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
|
||||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.2'
|
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.2'
|
||||||
@@ -73,29 +70,18 @@ dependencies {
|
|||||||
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
|
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
|
||||||
debugImplementation 'androidx.compose.ui:ui-tooling'
|
debugImplementation 'androidx.compose.ui:ui-tooling'
|
||||||
debugImplementation 'androidx.compose.ui:ui-test-manifest'
|
debugImplementation 'androidx.compose.ui:ui-test-manifest'
|
||||||
def room_version = "2.5.0"
|
|
||||||
implementation("io.coil-kt:coil-compose:2.6.0")
|
implementation("io.coil-kt:coil-compose:2.6.0")
|
||||||
|
|
||||||
|
def room_version = "2.6.1"
|
||||||
implementation "androidx.room:room-runtime:$room_version"
|
implementation "androidx.room:room-runtime:$room_version"
|
||||||
implementation "androidx.room:room-ktx:$room_version"
|
implementation "androidx.room:room-ktx:$room_version"
|
||||||
annotationProcessor "androidx.room:room-compiler:$room_version"
|
annotationProcessor "androidx.room:room-compiler:$room_version"
|
||||||
ksp "androidx.room:room-compiler:$room_version"
|
ksp "androidx.room:room-compiler:$room_version"
|
||||||
|
|
||||||
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
|
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.2")
|
||||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2"
|
|
||||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
|
|
||||||
implementation("com.google.android.material:material:1.10.0")
|
|
||||||
implementation 'jp.wasabeef:recyclerview-animators:4.0.2'
|
|
||||||
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
|
|
||||||
implementation 'com.google.android.flexbox:flexbox:3.0.0'
|
|
||||||
implementation ('androidx.swiperefreshlayout:swiperefreshlayout:1.1.0')
|
|
||||||
implementation ('com.squareup.retrofit2:retrofit:2.9.0')
|
implementation ('com.squareup.retrofit2:retrofit:2.9.0')
|
||||||
implementation ('com.squareup.retrofit2:converter-gson:2.9.0')
|
implementation ('com.squareup.retrofit2:converter-gson:2.9.0')
|
||||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.0"
|
||||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.5'
|
|
||||||
implementation "androidx.navigation:navigation-ui-ktx:2.7.5"
|
|
||||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.22"
|
|
||||||
implementation 'androidx.core:core-ktx:1.13.1'
|
implementation 'androidx.core:core-ktx:1.13.1'
|
||||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="com.lsp.view.fileprovider"
|
android:authorities="moe.uni.view.fileprovider"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:grantUriPermissions="true">
|
android:grantUriPermissions="true">
|
||||||
<meta-data
|
<meta-data
|
||||||
@@ -38,11 +38,7 @@
|
|||||||
android:name=".service.DownloadService"
|
android:name=".service.DownloadService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true" />
|
android:exported="true" />
|
||||||
<activity
|
|
||||||
android:name=".ui.activity.MainActivity"
|
|
||||||
android:exported="true">
|
|
||||||
|
|
||||||
</activity>
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
package com.lsp.view.ui
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.lifecycle.AbstractSavedStateViewModelFactory
|
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.SavedStateHandle
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.lsp.view.ui.fragment.adapter.PostAdapter
|
|
||||||
import com.lsp.view.repository.network.PostRepository
|
|
||||||
import androidx.savedstate.SavedStateRegistryOwner
|
|
||||||
import com.lsp.view.YandViewApplication
|
|
||||||
import com.lsp.view.bean.YandPost
|
|
||||||
import com.lsp.view.repository.datasource.CollectDatabase
|
|
||||||
import com.lsp.view.repository.datasource.CollectRepository
|
|
||||||
import com.lsp.view.repository.datasource.CollectRepositoryImpl
|
|
||||||
import com.lsp.view.repository.datasource.model.Collect
|
|
||||||
import com.lsp.view.repository.exception.NetworkErrorException
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import kotlinx.coroutines.flow.update
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
class MainViewModel(private val repository: PostRepository, context: Context):ViewModel() {
|
|
||||||
private val _uiState = MutableStateFlow(UiState())
|
|
||||||
val uiState:StateFlow<UiState>
|
|
||||||
get() = _uiState.asStateFlow()
|
|
||||||
private var fetchJob: Job? = null
|
|
||||||
private val TAG = this::class.java.simpleName
|
|
||||||
private val _toastMessage = MutableLiveData<String>()
|
|
||||||
val toastMessage
|
|
||||||
get() = _toastMessage as LiveData<String>
|
|
||||||
|
|
||||||
private val _postList = MutableLiveData<ArrayList<YandPost>>()
|
|
||||||
val postList get() = _postList as LiveData<ArrayList<YandPost>>
|
|
||||||
val adapter by lazy {
|
|
||||||
fetchPostByRefresh()
|
|
||||||
PostAdapter(context)
|
|
||||||
}
|
|
||||||
private val _collectList:MutableLiveData<List<Collect>> = MutableLiveData()
|
|
||||||
val collectList:LiveData<List<Collect>>
|
|
||||||
get() = _collectList
|
|
||||||
|
|
||||||
private val collectRepository: CollectRepository by lazy {
|
|
||||||
CollectRepositoryImpl(CollectDatabase.getDatabase(context).collectDao())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Volatile private var isProcessing = false
|
|
||||||
private val _tagsList = MutableLiveData<ArrayList<String>>()
|
|
||||||
val tagsList get() = _tagsList as LiveData<ArrayList<String>>
|
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun provideFactory(
|
|
||||||
repository: PostRepository,
|
|
||||||
context: Context,
|
|
||||||
owner: SavedStateRegistryOwner,
|
|
||||||
defaultArgs: Bundle? = null,
|
|
||||||
|
|
||||||
): AbstractSavedStateViewModelFactory =
|
|
||||||
object : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T : ViewModel> create(
|
|
||||||
key: String,
|
|
||||||
modelClass: Class<T>,
|
|
||||||
handle: SavedStateHandle
|
|
||||||
): T {
|
|
||||||
return MainViewModel(repository, context) as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
init {
|
|
||||||
//初始化写入
|
|
||||||
val configSp = context.getSharedPreferences("com.lsp.view_preferences", 0)
|
|
||||||
if (configSp.getString("source_name", null) == null) {
|
|
||||||
configSp.edit().putString("source_name", "yande.re").apply()
|
|
||||||
configSp.edit().putString("type", "0").apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
_uiState.update {
|
|
||||||
it.apply {
|
|
||||||
it.nowSourceName.postValue(configSp.getString("source_name",null))
|
|
||||||
}
|
|
||||||
|
|
||||||
it.copy(isSafe = configSp.getBoolean("safe_mode",true))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fetchNewPost() {
|
|
||||||
fetchJob?.cancel()
|
|
||||||
fetchJob = viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
_uiState.value.isRefreshing.postValue(true)
|
|
||||||
try {
|
|
||||||
val newPosts = repository.fetchPostData(
|
|
||||||
_uiState.value.nowSearchText.value,
|
|
||||||
_uiState.value.nowPage
|
|
||||||
)
|
|
||||||
val currentPosts = _postList.value ?: arrayListOf()
|
|
||||||
currentPosts.addAll(0,newPosts)
|
|
||||||
_postList.postValue(currentPosts)
|
|
||||||
} catch (e: NetworkErrorException) {
|
|
||||||
postNewToast(e.message.toString())
|
|
||||||
}
|
|
||||||
_uiState.value.isRefreshing.postValue(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun fetchPostByRefresh(){
|
|
||||||
_uiState.update {
|
|
||||||
it.copy(nowPage = 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchNewPost()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun fetchPostBySearch(searchTarget:String){
|
|
||||||
_uiState.update {
|
|
||||||
it.apply {
|
|
||||||
it.nowSearchText.postValue(searchTarget)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchNewPost()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun fetchMore(){
|
|
||||||
_uiState.value.nowPage++
|
|
||||||
fetchNewPost()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateSafeMode(mode:Boolean){
|
|
||||||
_uiState.update {
|
|
||||||
it.copy(isSafe = mode)
|
|
||||||
}
|
|
||||||
fetchNewPost()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateNowSource(source:String){
|
|
||||||
_uiState.value.nowSourceName.postValue(source)
|
|
||||||
fetchPostByRefresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCollectList(){
|
|
||||||
viewModelScope.launch {
|
|
||||||
_collectList.postValue(collectRepository.getAllCollect())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addCollect(collect: Collect){
|
|
||||||
if (!isProcessing){
|
|
||||||
viewModelScope.launch {
|
|
||||||
collectRepository.addNewCollect(collect)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeCollect(collect:Collect){
|
|
||||||
|
|
||||||
if (!isProcessing){
|
|
||||||
viewModelScope.launch {
|
|
||||||
collectRepository.removeCollect(collect)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getCollectByPostId(postId:String) = viewModelScope.async {
|
|
||||||
val type = YandViewApplication.context?.getSharedPreferences("com.lsp.view_preferences",Context.MODE_PRIVATE)?.getString("source_name", "yande.re")
|
|
||||||
collectRepository.getCollectByPostId(postId,type!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun postNewToast(content:String){
|
|
||||||
_toastMessage.postValue(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.lsp.view.ui
|
|
||||||
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
|
|
||||||
data class UiState(
|
|
||||||
var showSearchBar:Boolean = false,
|
|
||||||
val isRefreshing:MutableLiveData<Boolean> = MutableLiveData(),
|
|
||||||
var nowSearchText:MutableLiveData<String> = MutableLiveData(""),
|
|
||||||
val nowSourceName: MutableLiveData<String> = MutableLiveData(),
|
|
||||||
val isSafe: Boolean = true, //安全模式
|
|
||||||
var nowPage:Int = 1,
|
|
||||||
)
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package com.lsp.view.ui.activity
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
|
||||||
import androidx.navigation.ui.setupWithNavController
|
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
|
||||||
import com.lsp.view.R
|
|
||||||
import com.lsp.view.ui.MainViewModel
|
|
||||||
import com.lsp.view.repository.network.PostRepository
|
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
|
||||||
val TAG = javaClass.simpleName
|
|
||||||
lateinit var viewModel: MainViewModel
|
|
||||||
lateinit var bottomNav:BottomNavigationView
|
|
||||||
val repository = PostRepository()
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_main)
|
|
||||||
|
|
||||||
viewModel = MainViewModel.provideFactory(repository, this,this).create(MainViewModel::class.java)
|
|
||||||
|
|
||||||
bottomNav = findViewById(R.id.bottom_navigation)
|
|
||||||
|
|
||||||
viewModel.toastMessage.observe(this){
|
|
||||||
Toast.makeText(this,it,Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
|
|
||||||
val navController = navHostFragment.navController
|
|
||||||
bottomNav.setupWithNavController(navController)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
|
|
||||||
//加载源改变
|
|
||||||
val configSp = getSharedPreferences("com.lsp.view_preferences", 0)
|
|
||||||
|
|
||||||
val nowSourceName = configSp.getString("source_name", null)
|
|
||||||
|
|
||||||
if (nowSourceName != null && viewModel.uiState.value.nowSourceName.value != nowSourceName){
|
|
||||||
viewModel.updateNowSource(nowSourceName)
|
|
||||||
}
|
|
||||||
|
|
||||||
val nowMode = configSp.getBoolean("safe_mode", true)
|
|
||||||
if (viewModel.uiState.value.isSafe != nowMode){
|
|
||||||
viewModel.updateSafeMode(nowMode)
|
|
||||||
Log.e(TAG,nowMode.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
package com.lsp.view.ui.fragment
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.animation.AnimationUtils
|
|
||||||
import androidx.navigation.Navigation
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
|
||||||
import com.lsp.view.ui.fragment.adapter.PostAdapter
|
|
||||||
import com.lsp.view.R
|
|
||||||
import com.lsp.view.ui.activity.MainActivity
|
|
||||||
import com.lsp.view.bean.Post
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple [Fragment] subclass.
|
|
||||||
* create an instance of this fragment.
|
|
||||||
*/
|
|
||||||
class CollectFragment : Fragment() {
|
|
||||||
private lateinit var activityContext: MainActivity
|
|
||||||
private val collectAdapter by lazy {
|
|
||||||
PostAdapter(activityContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
activityContext = requireActivity() as MainActivity
|
|
||||||
|
|
||||||
activityContext.viewModel.getCollectList()
|
|
||||||
|
|
||||||
activityContext.viewModel.collectList.observe(this){
|
|
||||||
collectAdapter.pushNewData(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
// Inflate the layout for this fragment
|
|
||||||
return inflater.inflate(R.layout.fragment_collect, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
//刷新
|
|
||||||
val refresh =
|
|
||||||
view.findViewById<androidx.swiperefreshlayout.widget.SwipeRefreshLayout>(R.id.swipeRefreshLayout)
|
|
||||||
|
|
||||||
activityContext.viewModel.uiState.value.isRefreshing.observe(activityContext) {
|
|
||||||
refresh.isRefreshing = it
|
|
||||||
}
|
|
||||||
|
|
||||||
collectAdapter.setOnListItemClick(object : PostAdapter.OnListItemClick {
|
|
||||||
override fun setOnListItemClick(post: Post) {
|
|
||||||
ImageFragment.navigationToImageFragment(activityContext,post,view,R.id.action_collectFragment_to_imageFragment)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
view.findViewById<RecyclerView>(R.id.recyclerview).apply {
|
|
||||||
val layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
|
|
||||||
this.layoutManager = layoutManager
|
|
||||||
this.adapter = collectAdapter
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
if (activityContext.bottomNav.visibility == View.GONE){
|
|
||||||
val slideOutAnimation = AnimationUtils.loadAnimation(context, R.anim.slide_on_bottom)
|
|
||||||
activityContext.bottomNav.startAnimation(slideOutAnimation)
|
|
||||||
activityContext.bottomNav.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,218 +0,0 @@
|
|||||||
package com.lsp.view.ui.fragment
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.content.pm.ResolveInfo
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Environment
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.animation.AnimationUtils
|
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.core.content.FileProvider
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.navigation.Navigation
|
|
||||||
import com.bumptech.glide.Glide
|
|
||||||
import com.bumptech.glide.load.model.GlideUrl
|
|
||||||
import com.bumptech.glide.load.model.LazyHeaders
|
|
||||||
import com.google.android.material.bottomappbar.BottomAppBar
|
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
import com.lsp.view.R
|
|
||||||
import com.lsp.view.YandViewApplication
|
|
||||||
import com.lsp.view.ui.activity.MainActivity
|
|
||||||
import com.lsp.view.bean.Post
|
|
||||||
import com.lsp.view.repository.datasource.model.Collect
|
|
||||||
import com.lsp.view.repository.datasource.model.Collect.Companion.toCollect
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class ImageFragment : Fragment() {
|
|
||||||
private val post by lazy {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
||||||
arguments?.getParcelable("post",Post::class.java)
|
|
||||||
}else{
|
|
||||||
arguments?.getParcelable("post")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Volatile private var isCollect = false
|
|
||||||
private val activityContext : MainActivity by lazy {
|
|
||||||
requireActivity() as MainActivity
|
|
||||||
}
|
|
||||||
private lateinit var collectBtn:MenuItem
|
|
||||||
private lateinit var collect:Collect
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
// Inflate the layout for this fragment
|
|
||||||
return inflater.inflate(R.layout.fragment_image, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
val bottomAppBar = view.findViewById<BottomAppBar>(R.id.bottomAppBar)
|
|
||||||
collectBtn = bottomAppBar.menu.findItem(R.id.collect_menu_btn)
|
|
||||||
collectBtn.setIcon(R.drawable.ic_bashline_unfavorite_24)
|
|
||||||
bottomAppBar.setOnMenuItemClickListener {
|
|
||||||
when(it.itemId){
|
|
||||||
R.id.share_menu_btn ->{
|
|
||||||
post?.sampleUrl?.let { it1 -> share(it1,activityContext) }
|
|
||||||
true
|
|
||||||
}
|
|
||||||
R.id.collect_menu_btn ->{
|
|
||||||
if (!isCollect){
|
|
||||||
collect = post!!.toCollect()
|
|
||||||
collectIt(collect)
|
|
||||||
}else{
|
|
||||||
unCollectIt(collect)
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {false}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lifecycleScope.launch {
|
|
||||||
post?.postId?.let {
|
|
||||||
val collectPost = activityContext.viewModel.getCollectByPostId(it)
|
|
||||||
val result = collectPost.await()
|
|
||||||
if (result != null){
|
|
||||||
collect = result
|
|
||||||
collectBtn.setIcon(R.drawable.ic_baseline_favorite_24)
|
|
||||||
isCollect = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val downloadBtn = view.findViewById<FloatingActionButton>(R.id.download_btn)
|
|
||||||
downloadBtn.setOnClickListener {
|
|
||||||
lifecycleScope.launch {
|
|
||||||
if (post!=null){
|
|
||||||
download(post!!.fileUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (post!=null){
|
|
||||||
val imageContent = view.findViewById<ImageView>(R.id.image_content)
|
|
||||||
val glideUrl = GlideUrl(
|
|
||||||
post!!.sampleUrl,
|
|
||||||
LazyHeaders.Builder().addHeader("User-Agent", YandViewApplication.UA)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
Glide.with(this).load(glideUrl).into(imageContent)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun collectIt(collect: Collect){
|
|
||||||
activityContext.viewModel.addCollect(collect)
|
|
||||||
collectBtn.setIcon(R.drawable.ic_baseline_favorite_24)
|
|
||||||
isCollect = true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun unCollectIt(collect:Collect){
|
|
||||||
activityContext.viewModel.removeCollect(collect)
|
|
||||||
collectBtn.setIcon(R.drawable.ic_bashline_unfavorite_24)
|
|
||||||
isCollect = false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun download(fileUrl: String){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun share(url:String,context: Context){
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
val bitmap = Glide.with(context).asBitmap().load(url).submit().get()
|
|
||||||
val path = File("${context.cacheDir}/image")
|
|
||||||
val split = url.split("/")
|
|
||||||
val fileName = split[split.size - 1]
|
|
||||||
if (!path.exists())
|
|
||||||
path.mkdirs()
|
|
||||||
|
|
||||||
|
|
||||||
var file = File("${context.cacheDir}/image/$fileName")
|
|
||||||
val downloadFile =
|
|
||||||
File("${Environment.getExternalStorageDirectory()}/${Environment.DIRECTORY_PICTURES}/LspMake/$fileName")
|
|
||||||
|
|
||||||
if (downloadFile.exists()){
|
|
||||||
file = downloadFile
|
|
||||||
}else if (!file.exists()) {
|
|
||||||
file.outputStream().apply {
|
|
||||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val imageUri = FileProvider.getUriForFile(
|
|
||||||
context,
|
|
||||||
"com.lsp.view.fileprovider",
|
|
||||||
file
|
|
||||||
|
|
||||||
)
|
|
||||||
context.grantUriPermission(
|
|
||||||
"com.lsp.view",
|
|
||||||
imageUri,
|
|
||||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
|
||||||
)
|
|
||||||
val shareIntent = Intent(Intent.ACTION_SEND)
|
|
||||||
shareIntent.type = "image/*"
|
|
||||||
shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri)
|
|
||||||
shareIntent.putExtra(Intent.EXTRA_TITLE,fileName)
|
|
||||||
val intent = Intent.createChooser(shareIntent, R.string.title_share.toString())
|
|
||||||
val resInfoList: List<ResolveInfo> = if (Build.VERSION.SDK_INT < 33) {
|
|
||||||
context.packageManager
|
|
||||||
.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
|
|
||||||
} else {
|
|
||||||
context.packageManager.queryIntentActivities(
|
|
||||||
intent,
|
|
||||||
PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY.toLong())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
for (resolveInfo in resInfoList) {
|
|
||||||
val packageName = resolveInfo.activityInfo.packageName
|
|
||||||
context.grantUriPermission(
|
|
||||||
packageName,
|
|
||||||
imageUri,
|
|
||||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
||||||
)
|
|
||||||
}
|
|
||||||
context.startActivity(intent)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object{
|
|
||||||
fun navigationToImageFragment(context:MainActivity ,post:Post,view:View,fragmentId:Int){
|
|
||||||
val bundle = Bundle()
|
|
||||||
bundle.putParcelable("post",post)
|
|
||||||
val tags = post.tags?.split(",")?.toList()
|
|
||||||
|
|
||||||
context.viewModel.tagsList.value?.apply {
|
|
||||||
clear()
|
|
||||||
tags?.let { addAll(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
Navigation.findNavController(view).navigate(fragmentId,bundle)
|
|
||||||
val slideOutAnimation = AnimationUtils.loadAnimation(context,
|
|
||||||
R.anim.slide_out_bottom
|
|
||||||
)
|
|
||||||
context.bottomNav.startAnimation(slideOutAnimation)
|
|
||||||
context.bottomNav.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
package com.lsp.view.ui.fragment
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.animation.AnimationUtils
|
|
||||||
import android.view.inputmethod.EditorInfo
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.navigation.Navigation
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
|
||||||
import com.google.android.material.search.SearchBar
|
|
||||||
import com.google.android.material.search.SearchView
|
|
||||||
import com.lsp.view.ui.fragment.adapter.PostAdapter
|
|
||||||
import com.lsp.view.R
|
|
||||||
import com.lsp.view.ui.activity.MainActivity
|
|
||||||
import com.lsp.view.bean.Post
|
|
||||||
import com.lsp.view.ui.MainViewModel
|
|
||||||
|
|
||||||
class PostListFragment:Fragment() {
|
|
||||||
private val viewModel: MainViewModel by lazy {
|
|
||||||
ViewModelProvider(requireActivity(),
|
|
||||||
MainViewModel.provideFactory(activityContext.repository,requireContext(),this)).get(
|
|
||||||
MainViewModel::class.java)
|
|
||||||
}
|
|
||||||
private lateinit var activityContext: MainActivity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
return inflater.inflate(R.layout.fragment_list, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
activityContext = requireActivity() as MainActivity
|
|
||||||
val searchBar = view.findViewById<SearchBar>(R.id.search_bar)
|
|
||||||
|
|
||||||
val searchView = view.findViewById<SearchView>(R.id.search_view)
|
|
||||||
searchView.editText.setOnEditorActionListener { v, actionId, event ->
|
|
||||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
|
||||||
viewModel.fetchPostBySearch(searchView.text.toString())
|
|
||||||
searchBar.setText(searchView.text)
|
|
||||||
searchView.hide()
|
|
||||||
}
|
|
||||||
|
|
||||||
return@setOnEditorActionListener false
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.uiState.value.nowSearchText.observe(requireActivity()){
|
|
||||||
searchView.setText(it)
|
|
||||||
searchBar.setText(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
//刷新
|
|
||||||
val refresh =
|
|
||||||
view.findViewById<androidx.swiperefreshlayout.widget.SwipeRefreshLayout>(R.id.swipeRefreshLayout)
|
|
||||||
viewModel.uiState.value.isRefreshing.observe(activityContext) {
|
|
||||||
refresh.isRefreshing = it
|
|
||||||
}
|
|
||||||
refresh.setOnRefreshListener {
|
|
||||||
viewModel.fetchPostByRefresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.postList.observe(activityContext){
|
|
||||||
viewModel.adapter.pushNewData(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.adapter.apply {
|
|
||||||
setLoadMoreListener(object : PostAdapter.OnScrollToBottom {
|
|
||||||
override fun event(position: Int) {
|
|
||||||
viewModel.fetchMore()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
view.findViewById<RecyclerView>(R.id.recyclerview).apply {
|
|
||||||
val layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
|
|
||||||
this.layoutManager = layoutManager
|
|
||||||
this.adapter = viewModel.adapter
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.adapter.setOnListItemClick(object : PostAdapter.OnListItemClick {
|
|
||||||
override fun setOnListItemClick(post: Post) {
|
|
||||||
ImageFragment.navigationToImageFragment(activityContext,post,view,R.id.action_postListFragment_to_imageFragment)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
if (activityContext.bottomNav.visibility == View.GONE){
|
|
||||||
val slideOutAnimation = AnimationUtils.loadAnimation(context, R.anim.slide_on_bottom)
|
|
||||||
activityContext.bottomNav.startAnimation(slideOutAnimation)
|
|
||||||
activityContext.bottomNav.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.lsp.view.ui.fragment
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
|
||||||
import com.lsp.view.R
|
|
||||||
|
|
||||||
class SettingsFragment : PreferenceFragmentCompat() {
|
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
||||||
setPreferencesFromResource(R.xml.root_preferences, rootKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
package com.lsp.view.ui.fragment.adapter
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.bumptech.glide.Glide
|
|
||||||
import com.bumptech.glide.load.model.GlideUrl
|
|
||||||
import com.bumptech.glide.load.model.LazyHeaders
|
|
||||||
import com.lsp.view.R
|
|
||||||
import com.lsp.view.YandViewApplication
|
|
||||||
import com.lsp.view.bean.Post
|
|
||||||
|
|
||||||
|
|
||||||
class PostAdapter(val context: Context,private val postList: ArrayList<Post> = ArrayList()):
|
|
||||||
RecyclerView.Adapter<PostAdapter.ViewHolder>() {
|
|
||||||
val TAG = this::class.java.simpleName
|
|
||||||
private var inBottom:Boolean = false//当前列表是否在底部
|
|
||||||
|
|
||||||
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
|
||||||
val picImage: ImageView = view.findViewById(R.id.image)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun pushNewData(list: List<Post>) {
|
|
||||||
if (inBottom) {
|
|
||||||
//在底部,则追加数据
|
|
||||||
val pos = postList.size
|
|
||||||
postList.addAll(list)
|
|
||||||
notifyItemRangeInserted(pos - 1, list.size)
|
|
||||||
} else {
|
|
||||||
//不在则刷新数据
|
|
||||||
val oldSize = postList.size
|
|
||||||
postList.clear()
|
|
||||||
notifyItemRangeRemoved(0, oldSize)
|
|
||||||
postList.addAll(list)
|
|
||||||
notifyItemRangeInserted(0, list.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
inBottom = false//加入新数据后不在底部,若仍在底部说明无更多数据,也不必处理
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private lateinit var mOnListItemClick: OnListItemClick
|
|
||||||
interface OnListItemClick {
|
|
||||||
fun setOnListItemClick(post:Post)
|
|
||||||
}
|
|
||||||
fun setOnListItemClick(mOnListItemClick: OnListItemClick) {
|
|
||||||
this.mOnListItemClick = mOnListItemClick
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
||||||
val view = LayoutInflater.from(context).inflate(R.layout.img_item_layout, parent, false)
|
|
||||||
val viewHolder = ViewHolder(view)
|
|
||||||
|
|
||||||
viewHolder.picImage.setOnClickListener {
|
|
||||||
val position = viewHolder.adapterPosition
|
|
||||||
mOnListItemClick.setOnListItemClick(postList[position])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return viewHolder
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var mScrollToBottom: OnScrollToBottom
|
|
||||||
|
|
||||||
interface OnScrollToBottom {
|
|
||||||
fun event(position: Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setLoadMoreListener(mLoadMoreListener: OnScrollToBottom) {
|
|
||||||
this.mScrollToBottom = mLoadMoreListener
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun preLoad(p:Int){
|
|
||||||
if (p%20==0){
|
|
||||||
//执行预加载
|
|
||||||
val last:Int = if (postList.size-p<20){
|
|
||||||
postList.size-1
|
|
||||||
}else{
|
|
||||||
p+19
|
|
||||||
}
|
|
||||||
for(index in p..last){
|
|
||||||
if (p>6) {
|
|
||||||
val source: String = postList[index].sampleUrl
|
|
||||||
val glideUrl = GlideUrl(
|
|
||||||
source,
|
|
||||||
LazyHeaders.Builder().addHeader("User-Agent", YandViewApplication.UA)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
Glide.with(context).download(glideUrl).preload()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
|
||||||
preLoad(position)
|
|
||||||
|
|
||||||
val post = postList[position]
|
|
||||||
|
|
||||||
val source: String = post.sampleUrl
|
|
||||||
|
|
||||||
val height = postList[position].sampleHeight
|
|
||||||
val width = postList[position].sampleWidth
|
|
||||||
|
|
||||||
//图片过长则缩减高度以保证显示完整
|
|
||||||
if (width > height){
|
|
||||||
holder.picImage.layoutParams.height = height / 2
|
|
||||||
}else {
|
|
||||||
holder.picImage.layoutParams.height = height
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val glideUrl = GlideUrl(
|
|
||||||
source,
|
|
||||||
LazyHeaders.Builder().addHeader("User-Agent", YandViewApplication.UA)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
Glide.with(context).load(glideUrl).into(holder.picImage)
|
|
||||||
|
|
||||||
if (position == postList.size - 1 && postList.size > 6 ) {
|
|
||||||
//到达底部
|
|
||||||
inBottom = true
|
|
||||||
if (this::mScrollToBottom.isInitialized) {
|
|
||||||
mScrollToBottom.event(position)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
|
||||||
return postList.size
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package com.lsp.view.ui.fragment.adapter
|
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.lsp.view.R
|
|
||||||
|
|
||||||
class TagsAdapter(private val tagList:List<String>):RecyclerView.Adapter<TagsAdapter.ViewHolder>() {
|
|
||||||
inner class ViewHolder(view:View):RecyclerView.ViewHolder(view) {
|
|
||||||
val tagItem = view.findViewById<TextView>(R.id.tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
||||||
val view =
|
|
||||||
LayoutInflater.from(parent.context).inflate(R.layout.tags_item_layout, parent, false)
|
|
||||||
val viewHolder = ViewHolder(view)
|
|
||||||
|
|
||||||
return viewHolder
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount() = tagList.size
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
|
||||||
holder.tagItem.text = tagList[position]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-4
@@ -1,9 +1,8 @@
|
|||||||
package com.lsp.view
|
package moe.uni.view
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.google.android.material.color.DynamicColors
|
|
||||||
|
|
||||||
class YandViewApplication : Application(), DefaultLifecycleObserver {
|
class YandViewApplication : Application(), DefaultLifecycleObserver {
|
||||||
|
|
||||||
@@ -11,8 +10,6 @@ class YandViewApplication : Application(), DefaultLifecycleObserver {
|
|||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super<Application>.onCreate()
|
super<Application>.onCreate()
|
||||||
context = applicationContext
|
context = applicationContext
|
||||||
|
|
||||||
DynamicColors.applyToActivitiesIfAvailable(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.bean
|
package moe.uni.view.bean
|
||||||
|
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.bean
|
package moe.uni.view.bean
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.common
|
package moe.uni.view.common
|
||||||
|
|
||||||
class Config(val safeMode:Boolean,val source:String) {
|
class Config(val safeMode:Boolean,val source:String) {
|
||||||
companion object{
|
companion object{
|
||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.common
|
package moe.uni.view.common
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@@ -13,7 +13,7 @@ import androidx.core.content.FileProvider
|
|||||||
import androidx.core.graphics.drawable.toBitmap
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import com.lsp.view.R
|
import moe.uni.view.R
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -95,7 +95,7 @@ suspend fun getImageInfo(url: String, context: Context): ImageInfo {
|
|||||||
}
|
}
|
||||||
val imageUri = FileProvider.getUriForFile(
|
val imageUri = FileProvider.getUriForFile(
|
||||||
context,
|
context,
|
||||||
"com.lsp.view.fileprovider",
|
"moe.uni.view.fileprovider",
|
||||||
file
|
file
|
||||||
)
|
)
|
||||||
return ImageInfo(path = file.path, name = fileName, uri = imageUri)
|
return ImageInfo(path = file.path, name = fileName, uri = imageUri)
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.common
|
package moe.uni.view.common
|
||||||
|
|
||||||
object PreKV {
|
object PreKV {
|
||||||
const val SOURCE_NAME = "source_name"
|
const val SOURCE_NAME = "source_name"
|
||||||
@@ -6,5 +6,5 @@ object PreKV {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Pre{
|
object Pre{
|
||||||
const val NAME = "com.lsp.view_preferences"
|
const val NAME = "moe.uni.view_preferences"
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
package com.lsp.view.common
|
package moe.uni.view.common
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.lsp.view.YandViewApplication
|
import moe.uni.view.YandViewApplication
|
||||||
|
|
||||||
object PreUtils {
|
object PreUtils {
|
||||||
private val PRE = YandViewApplication.context!!.getSharedPreferences(Pre.NAME,Context.MODE_PRIVATE)
|
private val PRE = YandViewApplication.context!!.getSharedPreferences(Pre.NAME,Context.MODE_PRIVATE)
|
||||||
+3
-3
@@ -1,11 +1,11 @@
|
|||||||
package com.lsp.view.repository.datasource
|
package moe.uni.view.repository.datasource
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import com.lsp.view.repository.datasource.dao.CollectDao
|
import moe.uni.view.repository.datasource.dao.CollectDao
|
||||||
import com.lsp.view.repository.datasource.model.Collect
|
import moe.uni.view.repository.datasource.model.Collect
|
||||||
|
|
||||||
@Database(entities = [Collect::class], version = 1,exportSchema = false)
|
@Database(entities = [Collect::class], version = 1,exportSchema = false)
|
||||||
abstract class CollectDatabase: RoomDatabase(){
|
abstract class CollectDatabase: RoomDatabase(){
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
package com.lsp.view.repository.datasource
|
package moe.uni.view.repository.datasource
|
||||||
|
|
||||||
import com.lsp.view.repository.datasource.model.Collect
|
import moe.uni.view.repository.datasource.model.Collect
|
||||||
|
|
||||||
interface CollectRepository {
|
interface CollectRepository {
|
||||||
suspend fun addNewCollect(collect: Collect)
|
suspend fun addNewCollect(collect: Collect)
|
||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
package com.lsp.view.repository.datasource
|
package moe.uni.view.repository.datasource
|
||||||
|
|
||||||
import com.lsp.view.repository.datasource.dao.CollectDao
|
import moe.uni.view.repository.datasource.dao.CollectDao
|
||||||
import com.lsp.view.repository.datasource.model.Collect
|
import moe.uni.view.repository.datasource.model.Collect
|
||||||
|
|
||||||
class CollectRepositoryImpl(private val collectDao:CollectDao):CollectRepository {
|
class CollectRepositoryImpl(private val collectDao:CollectDao):CollectRepository {
|
||||||
override suspend fun addNewCollect(collect: Collect) {
|
override suspend fun addNewCollect(collect: Collect) {
|
||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
package com.lsp.view.repository.datasource.dao
|
package moe.uni.view.repository.datasource.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.lsp.view.repository.datasource.model.Collect
|
import moe.uni.view.repository.datasource.model.Collect
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface CollectDao {
|
interface CollectDao {
|
||||||
+4
-4
@@ -1,11 +1,11 @@
|
|||||||
package com.lsp.view.repository.datasource.model
|
package moe.uni.view.repository.datasource.model
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import com.lsp.view.YandViewApplication
|
import moe.uni.view.YandViewApplication
|
||||||
import com.lsp.view.bean.Post
|
import moe.uni.view.bean.Post
|
||||||
|
|
||||||
@Entity(tableName = "collect")
|
@Entity(tableName = "collect")
|
||||||
data class Collect(
|
data class Collect(
|
||||||
@@ -28,7 +28,7 @@ data class Collect(
|
|||||||
sampleWeight:Int,
|
sampleWeight:Int,
|
||||||
tags:String?
|
tags:String?
|
||||||
): this(0, postId, sampleUrl, rating, fileUrl, sampleHeight, sampleWeight,
|
): this(0, postId, sampleUrl, rating, fileUrl, sampleHeight, sampleWeight,
|
||||||
YandViewApplication.context?.getSharedPreferences("com.lsp.view_preferences",Context.MODE_PRIVATE)?.getString("source_name", "yande.re")!!,tags)
|
YandViewApplication.context?.getSharedPreferences("moe.uni.view_preferences",Context.MODE_PRIVATE)?.getString("source_name", "yande.re")!!,tags)
|
||||||
companion object{
|
companion object{
|
||||||
fun Post.toCollect():Collect = Collect(this.postId,this.sampleUrl,this.rating,this.fileUrl,this.sampleHeight,this.sampleWidth ,this.tags)
|
fun Post.toCollect():Collect = Collect(this.postId,this.sampleUrl,this.rating,this.fileUrl,this.sampleHeight,this.sampleWidth ,this.tags)
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.repository.exception
|
package moe.uni.view.repository.exception
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
|
||||||
+1
-3
@@ -1,6 +1,4 @@
|
|||||||
package com.lsp.view.repository.exception
|
package moe.uni.view.repository.exception
|
||||||
|
|
||||||
import okhttp3.ResponseBody
|
|
||||||
|
|
||||||
class NetworkErrorException(override val message: String?) : LoggerException(message) {
|
class NetworkErrorException(override val message: String?) : LoggerException(message) {
|
||||||
}
|
}
|
||||||
+1
-3
@@ -1,6 +1,4 @@
|
|||||||
package com.lsp.view.repository.exception
|
package moe.uni.view.repository.exception
|
||||||
|
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
class UnableConstructObjectException(override val message: String?):LoggerException(message) {
|
class UnableConstructObjectException(override val message: String?):LoggerException(message) {
|
||||||
}
|
}
|
||||||
+5
-10
@@ -1,14 +1,9 @@
|
|||||||
package com.lsp.view.repository.network
|
package moe.uni.view.repository.network
|
||||||
|
|
||||||
import com.lsp.view.R
|
import moe.uni.view.repository.network.api.PostApi
|
||||||
import com.lsp.view.YandViewApplication
|
import moe.uni.view.repository.network.api.PostApiImpl
|
||||||
import com.lsp.view.repository.exception.UnableConstructObjectException
|
import moe.uni.view.bean.YandPost
|
||||||
import com.lsp.view.repository.network.api.PostApi
|
import moe.uni.view.common.Config
|
||||||
import com.lsp.view.repository.network.api.PostApiImpl
|
|
||||||
import com.lsp.view.bean.YandPost
|
|
||||||
import com.lsp.view.common.Config
|
|
||||||
import com.lsp.view.common.Pre
|
|
||||||
import com.lsp.view.common.PreKV
|
|
||||||
|
|
||||||
class PostDataSource {
|
class PostDataSource {
|
||||||
companion object{
|
companion object{
|
||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
package com.lsp.view.repository.network
|
package moe.uni.view.repository.network
|
||||||
|
|
||||||
import com.lsp.view.bean.YandPost
|
import moe.uni.view.bean.YandPost
|
||||||
import com.lsp.view.common.Config
|
import moe.uni.view.common.Config
|
||||||
|
|
||||||
|
|
||||||
class PostRepository {
|
class PostRepository {
|
||||||
+5
-5
@@ -1,9 +1,9 @@
|
|||||||
package com.lsp.view.repository.network.api
|
package moe.uni.view.repository.network.api
|
||||||
|
|
||||||
import com.lsp.view.repository.network.Load
|
import moe.uni.view.repository.network.Load
|
||||||
import com.lsp.view.bean.Post
|
import moe.uni.view.bean.Post
|
||||||
import com.lsp.view.bean.YandPost
|
import moe.uni.view.bean.YandPost
|
||||||
import com.lsp.view.repository.exception.NetworkErrorException
|
import moe.uni.view.repository.exception.NetworkErrorException
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
|
|
||||||
interface PostApi {
|
interface PostApi {
|
||||||
+5
-5
@@ -1,9 +1,9 @@
|
|||||||
package com.lsp.view.repository.network.api
|
package moe.uni.view.repository.network.api
|
||||||
|
|
||||||
import com.lsp.view.repository.network.Load
|
import moe.uni.view.repository.network.Load
|
||||||
import com.lsp.view.repository.network.retrofit.PostService
|
import moe.uni.view.repository.network.retrofit.PostService
|
||||||
import com.lsp.view.repository.network.retrofit.ServiceCreator
|
import moe.uni.view.repository.network.retrofit.ServiceCreator
|
||||||
import com.lsp.view.bean.YandPost
|
import moe.uni.view.bean.YandPost
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
package com.lsp.view.repository.network.retrofit
|
package moe.uni.view.repository.network.retrofit
|
||||||
|
|
||||||
import com.lsp.view.bean.YandPost
|
import moe.uni.view.bean.YandPost
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.repository.network.retrofit
|
package moe.uni.view.repository.network.retrofit
|
||||||
|
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
package com.lsp.view.service
|
package moe.uni.view.service
|
||||||
|
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.media.MediaScannerConnection
|
import android.media.MediaScannerConnection
|
||||||
import android.os.*
|
import android.os.*
|
||||||
import com.lsp.view.repository.network.retrofit.ServiceCreator
|
import moe.uni.view.repository.network.retrofit.ServiceCreator
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
+5
-5
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.ui.compose
|
package moe.uni.view.ui.compose
|
||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@@ -14,14 +14,14 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import com.lsp.view.ui.compose.theme.LspViewTheme
|
import moe.uni.view.ui.compose.theme.LspViewTheme
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.lsp.view.service.DownloadService
|
import moe.uni.view.service.DownloadService
|
||||||
import com.lsp.view.ui.compose.screen.DetailScreen
|
import moe.uni.view.ui.compose.screen.DetailScreen
|
||||||
import com.lsp.view.ui.compose.screen.PostListScreen
|
import moe.uni.view.ui.compose.screen.PostListScreen
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
package com.lsp.view.ui.compose
|
package moe.uni.view.ui.compose
|
||||||
|
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import com.lsp.view.bean.Post
|
import moe.uni.view.bean.Post
|
||||||
|
|
||||||
data class PostUiState(
|
data class PostUiState(
|
||||||
var refresh:MutableState<Boolean> = mutableStateOf(true),
|
var refresh:MutableState<Boolean> = mutableStateOf(true),
|
||||||
+5
-5
@@ -1,12 +1,12 @@
|
|||||||
package com.lsp.view.ui.compose
|
package moe.uni.view.ui.compose
|
||||||
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.lsp.view.bean.YandPost
|
import moe.uni.view.bean.YandPost
|
||||||
import com.lsp.view.repository.exception.NetworkErrorException
|
import moe.uni.view.repository.exception.NetworkErrorException
|
||||||
import com.lsp.view.repository.network.PostRepository
|
import moe.uni.view.repository.network.PostRepository
|
||||||
import com.lsp.view.service.Result
|
import moe.uni.view.service.Result
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
+7
-6
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.ui.compose.screen
|
package moe.uni.view.ui.compose.screen
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Box
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.Share
|
import androidx.compose.material.icons.filled.Share
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
@@ -29,10 +30,10 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.lsp.view.R
|
import moe.uni.view.R
|
||||||
import com.lsp.view.common.setWallpaper
|
import moe.uni.view.common.setWallpaper
|
||||||
import com.lsp.view.common.share
|
import moe.uni.view.common.share
|
||||||
import com.lsp.view.ui.compose.PostViewModel
|
import moe.uni.view.ui.compose.PostViewModel
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -77,7 +78,7 @@ fun DetailScreen(navController: NavController, viewModel: PostViewModel) {
|
|||||||
title = {},
|
title = {},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = { navController.popBackStack() }) {
|
IconButton(onClick = { navController.popBackStack() }) {
|
||||||
Icon(imageVector = Icons.Filled.ArrowBack, contentDescription = R.string.description_back.toString())
|
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = R.string.description_back.toString())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
+6
-6
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.ui.compose.screen
|
package moe.uni.view.ui.compose.screen
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
@@ -53,11 +53,11 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import coil.compose.SubcomposeAsyncImage
|
import coil.compose.SubcomposeAsyncImage
|
||||||
import coil.compose.SubcomposeAsyncImageContent
|
import coil.compose.SubcomposeAsyncImageContent
|
||||||
import com.lsp.view.bean.Post
|
import moe.uni.view.bean.Post
|
||||||
import com.lsp.view.common.Config
|
import moe.uni.view.common.Config
|
||||||
import com.lsp.view.ui.compose.NAV_ROUTE_DETAIL_SCREEN
|
import moe.uni.view.ui.compose.NAV_ROUTE_DETAIL_SCREEN
|
||||||
import com.lsp.view.ui.compose.PostViewModel
|
import moe.uni.view.ui.compose.PostViewModel
|
||||||
import com.lsp.view.ui.compose.widget.SearchBar
|
import moe.uni.view.ui.compose.widget.SearchBar
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.ui.compose.theme
|
package moe.uni.view.ui.compose.theme
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.ui.compose.theme
|
package moe.uni.view.ui.compose.theme
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.ui.compose.theme
|
package moe.uni.view.ui.compose.theme
|
||||||
|
|
||||||
import androidx.compose.material3.Typography
|
import androidx.compose.material3.Typography
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.lsp.view.ui.compose.widget
|
package moe.uni.view.ui.compose.widget
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<translate android:fromYDelta="100%p" android:toYDelta="0%p"
|
|
||||||
android:duration="400"/>
|
|
||||||
</set>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<translate android:fromYDelta="0%p" android:toYDelta="100%p"
|
|
||||||
android:duration="400"/>
|
|
||||||
</set>
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".ui.activity.MainActivity">
|
|
||||||
|
|
||||||
<androidx.fragment.app.FragmentContainerView
|
|
||||||
android:id="@+id/nav_host_fragment"
|
|
||||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:defaultNavHost="true"
|
|
||||||
app:navGraph="@navigation/nav_graph" />
|
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:id="@+id/bottom_navigation"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:menu="@menu/nav_menu" />
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
||||||
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".ui.fragment.CollectFragment">
|
|
||||||
|
|
||||||
<include layout="@layout/post_list_layout"/>
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
tools:context=".ui.fragment.ImageFragment">
|
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.github.chrisbanes.photoview.PhotoView
|
|
||||||
android:id="@+id/image_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"/>
|
|
||||||
<com.google.android.material.bottomappbar.BottomAppBar
|
|
||||||
android:id="@+id/bottomAppBar"
|
|
||||||
style="@style/Widget.Material3.BottomAppBar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
app:menu="@menu/image_bottom_menu" />
|
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
android:id="@+id/download_btn"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_anchor="@id/bottomAppBar"
|
|
||||||
app:srcCompat="@drawable/baseline_file_download_24"
|
|
||||||
android:contentDescription="@string/description_download" />
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<include layout="@layout/post_list_layout"/>
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
|
||||||
android:id="@+id/app_bar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
<com.google.android.material.search.SearchBar
|
|
||||||
android:id="@+id/search_bar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.search.SearchView
|
|
||||||
android:id="@+id/search_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_anchor="@id/search_bar">
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/search_tip"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
</com.google.android.material.search.SearchView>
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:elevation="20dp"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
app:cardCornerRadius="4dp"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
style="?attr/materialCardViewElevatedStyle"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/item_pic"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:id="@+id/image"/>
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
|
||||||
android:id="@+id/swipeRefreshLayout"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
tools:ignore="MissingConstraints">
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/recyclerview"/>
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
|
||||||
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:orientation="vertical">
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
android:id="@+id/appbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/actionBarSize">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/settings"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
<TextView
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/tag"/>
|
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
<item android:contentDescription="@string/description_share"
|
|
||||||
android:id="@+id/share_menu_btn"
|
|
||||||
android:title="@string/title_share"
|
|
||||||
android:icon="@drawable/ic_twotone_share_24"
|
|
||||||
app:showAsAction="ifRoom"/>
|
|
||||||
<item android:id="@+id/collect_menu_btn"
|
|
||||||
android:title="@string/title_collect"
|
|
||||||
android:icon="@drawable/ic_baseline_favorite_24"
|
|
||||||
app:showAsAction="ifRoom"/>
|
|
||||||
|
|
||||||
|
|
||||||
</menu>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<group android:checkableBehavior="single">
|
|
||||||
<item
|
|
||||||
android:id="@+id/postListFragment"
|
|
||||||
android:icon="@drawable/ic_baseline_insert_photo_24"
|
|
||||||
android:title="@string/item_gallery"/>
|
|
||||||
<item
|
|
||||||
android:id="@+id/collectFragment"
|
|
||||||
android:icon="@drawable/ic_baseline_favorite_24"
|
|
||||||
android:title="@string/item_collect"/>
|
|
||||||
<item
|
|
||||||
android:id="@+id/settingsFragment"
|
|
||||||
android:icon="@drawable/baseline_settings_24"
|
|
||||||
android:title="@string/item_settings"/>
|
|
||||||
</group>
|
|
||||||
</menu>
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/nav_graph"
|
|
||||||
app:startDestination="@id/postListFragment">
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/postListFragment"
|
|
||||||
android:name="com.lsp.view.ui.fragment.PostListFragment"
|
|
||||||
android:label="PostListFragment" >
|
|
||||||
<action
|
|
||||||
android:id="@+id/action_postListFragment_to_imageFragment"
|
|
||||||
app:destination="@id/imageFragment"
|
|
||||||
app:enterAnim="@anim/slide_on_bottom"
|
|
||||||
app:exitAnim="@anim/nav_default_exit_anim"
|
|
||||||
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
|
||||||
app:popExitAnim="@anim/slide_out_bottom" >
|
|
||||||
</action>
|
|
||||||
</fragment>
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/imageFragment"
|
|
||||||
android:name="com.lsp.view.ui.fragment.ImageFragment"
|
|
||||||
android:label="fragment_pic"
|
|
||||||
tools:layout="@layout/fragment_image" >
|
|
||||||
</fragment>
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/collectFragment"
|
|
||||||
android:name="com.lsp.view.ui.fragment.CollectFragment"
|
|
||||||
android:label="fragment_collect"
|
|
||||||
tools:layout="@layout/fragment_collect" >
|
|
||||||
<action
|
|
||||||
android:id="@+id/action_collectFragment_to_imageFragment"
|
|
||||||
app:destination="@id/imageFragment"
|
|
||||||
app:enterAnim="@anim/slide_on_bottom"
|
|
||||||
app:exitAnim="@anim/nav_default_exit_anim"
|
|
||||||
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
|
||||||
app:popExitAnim="@anim/slide_out_bottom"/>
|
|
||||||
</fragment>
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/settingsFragment"
|
|
||||||
android:name="com.lsp.view.ui.fragment.SettingsFragment"
|
|
||||||
android:label="SettingsFragment" />
|
|
||||||
</navigation>
|
|
||||||
+2
-2
@@ -6,9 +6,9 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:8.3.1'
|
classpath 'com.android.tools.build:gradle:8.3.2'
|
||||||
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10'
|
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10'
|
||||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.7.5"
|
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.7.7"
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
include ':app'
|
include ':app'
|
||||||
rootProject.name = "LspView"
|
rootProject.name = "YandView"
|
||||||
Reference in New Issue
Block a user