Issue#12 Add UserPreferences to always open the app when saving a video
This commit is contained in:
parent
eda8b95c89
commit
6b849b06bd
22 changed files with 255 additions and 11 deletions
|
|
@ -21,7 +21,7 @@ android {
|
|||
minSdkVersion 23
|
||||
targetSdkVersion 31
|
||||
versionCode 1
|
||||
versionName "1.0.0"
|
||||
versionName "1.3.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ android {
|
|||
}
|
||||
release {
|
||||
signingConfig signingConfigs.release
|
||||
debuggable false
|
||||
debuggable true
|
||||
shrinkResources true
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package org.fnives.tiktokdownloader.data.local
|
||||
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.fnives.tiktokdownloader.data.local.persistent.UserPreferencesStorage
|
||||
import org.fnives.tiktokdownloader.data.model.UserPreferences
|
||||
|
||||
class UserPreferencesLocalSource(private val userPreferencesStorage: UserPreferencesStorage) {
|
||||
|
||||
private val signal = MutableSharedFlow<Unit>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST).apply { tryEmit(Unit) }
|
||||
|
||||
fun get(): Flow<UserPreferences> = signal
|
||||
.map { getSync() }
|
||||
|
||||
fun getSync() = UserPreferences(alwaysOpenApp = userPreferencesStorage.openAppToIntent)
|
||||
|
||||
suspend fun set(userPreferences: UserPreferences) {
|
||||
if (userPreferences.alwaysOpenApp == userPreferencesStorage.openAppToIntent) return
|
||||
userPreferencesStorage.openAppToIntent = userPreferences.alwaysOpenApp
|
||||
signal.emit(Unit)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,13 +9,14 @@ import kotlin.properties.ReadOnlyProperty
|
|||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class SharedPreferencesManagerImpl private constructor(private val sharedPreferences: SharedPreferences) : SharedPreferencesManager {
|
||||
class SharedPreferencesManagerImpl private constructor(private val sharedPreferences: SharedPreferences) : SharedPreferencesManager, UserPreferencesStorage {
|
||||
|
||||
override var captchaTimeoutUntil: Long by LongDelegate(CAPTCHA_TIMEOUT_KEY)
|
||||
override var pendingVideos: Set<String> by StringSetDelegate(PENDING_VIDEO_KEY)
|
||||
override val pendingVideosFlow by StringSetFlowDelegate(PENDING_VIDEO_KEY)
|
||||
override var downloadedVideos: Set<String> by StringSetDelegate(DOWNLOADED_VIDEO_KEY)
|
||||
override val downloadedVideosFlow by StringSetFlowDelegate(DOWNLOADED_VIDEO_KEY)
|
||||
override var openAppToIntent: Boolean by BooleanDelegate(USER_PREFERENCE_ALWAYS_OPEN_APP)
|
||||
|
||||
class LongDelegate(private val key: String) : ReadWriteProperty<SharedPreferencesManagerImpl, Long> {
|
||||
override fun setValue(thisRef: SharedPreferencesManagerImpl, property: KProperty<*>, value: Long) {
|
||||
|
|
@ -26,6 +27,15 @@ class SharedPreferencesManagerImpl private constructor(private val sharedPrefere
|
|||
thisRef.sharedPreferences.getLong(key, 0)
|
||||
}
|
||||
|
||||
class BooleanDelegate(private val key: String) : ReadWriteProperty<SharedPreferencesManagerImpl, Boolean> {
|
||||
override fun setValue(thisRef: SharedPreferencesManagerImpl, property: KProperty<*>, value: Boolean) {
|
||||
thisRef.sharedPreferences.edit().putBoolean(key, value).apply()
|
||||
}
|
||||
|
||||
override fun getValue(thisRef: SharedPreferencesManagerImpl, property: KProperty<*>): Boolean =
|
||||
thisRef.sharedPreferences.getBoolean(key, false)
|
||||
}
|
||||
|
||||
class StringSetDelegate(private val key: String) : ReadWriteProperty<SharedPreferencesManagerImpl, Set<String>> {
|
||||
override fun setValue(thisRef: SharedPreferencesManagerImpl, property: KProperty<*>, value: Set<String>) {
|
||||
thisRef.sharedPreferences.edit().putStringSet(key, value).apply()
|
||||
|
|
@ -60,6 +70,7 @@ class SharedPreferencesManagerImpl private constructor(private val sharedPrefere
|
|||
private const val CAPTCHA_TIMEOUT_KEY = "CAPTCHA_TIMEOUT_KEY"
|
||||
private const val PENDING_VIDEO_KEY = "PENDING_VIDEO_KEY"
|
||||
private const val DOWNLOADED_VIDEO_KEY = "DOWNLOADED_VIDEO_KEY"
|
||||
private const val USER_PREFERENCE_ALWAYS_OPEN_APP = "USER_PREFERENCE_ALWAYS_OPEN_APP"
|
||||
|
||||
fun create(context: Context): SharedPreferencesManagerImpl =
|
||||
SharedPreferencesManagerImpl(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
package org.fnives.tiktokdownloader.data.local.persistent
|
||||
|
||||
interface UserPreferencesStorage {
|
||||
|
||||
var openAppToIntent: Boolean
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package org.fnives.tiktokdownloader.data.model
|
||||
|
||||
data class UserPreferences(val alwaysOpenApp: Boolean)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.fnives.tiktokdownloader.data.usecase
|
||||
|
||||
import org.fnives.tiktokdownloader.data.local.UserPreferencesLocalSource
|
||||
import org.fnives.tiktokdownloader.data.model.UserPreferences
|
||||
|
||||
class GetUserPreferences(private val userPreferencesLocalSource: UserPreferencesLocalSource) {
|
||||
|
||||
operator fun invoke(): UserPreferences = userPreferencesLocalSource.getSync()
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package org.fnives.tiktokdownloader.data.usecase
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.fnives.tiktokdownloader.data.local.UserPreferencesLocalSource
|
||||
import org.fnives.tiktokdownloader.data.model.UserPreferences
|
||||
|
||||
class ObserveUserPreferences(private val userPreferencesLocalSource: UserPreferencesLocalSource) {
|
||||
|
||||
operator fun invoke(): Flow<UserPreferences> = userPreferencesLocalSource.get()
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package org.fnives.tiktokdownloader.data.usecase
|
||||
|
||||
import org.fnives.tiktokdownloader.data.local.UserPreferencesLocalSource
|
||||
import org.fnives.tiktokdownloader.data.model.UserPreferences
|
||||
|
||||
class SetUserPreferences(private val userPreferencesLocalSource: UserPreferencesLocalSource) {
|
||||
|
||||
suspend operator fun invoke(userPreferences: UserPreferences) {
|
||||
userPreferencesLocalSource.set(userPreferences)
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,10 @@ object ServiceLocator {
|
|||
val permissionModule: PermissionModule
|
||||
get() = _permissionModule ?: throw IllegalStateException("$this.start has not been called!")
|
||||
|
||||
private var _useCaseModule: UseCaseModule? = null
|
||||
val useCaseModule: UseCaseModule
|
||||
get() = _useCaseModule ?: throw IllegalStateException("$this.start has not been called!")
|
||||
|
||||
fun viewModelFactory(
|
||||
savedStateRegistryOwner: SavedStateRegistryOwner,
|
||||
defaultArgs: Bundle
|
||||
|
|
@ -36,9 +40,13 @@ object ServiceLocator {
|
|||
|
||||
fun start(context: Context) {
|
||||
val androidFileManagementModule = AndroidFileManagementModule(context)
|
||||
val localSourceModule = LocalSourceModule(androidFileManagementModule)
|
||||
val networkModule = NetworkModule(DEFAULT_DELAY_BEFORE_REQUEST)
|
||||
val useCaseModule = UseCaseModule(localSourceModule, networkModule)
|
||||
val localSourceModule = LocalSourceModule(androidFileManagementModule = androidFileManagementModule)
|
||||
val networkModule = NetworkModule(delayBeforeRequest = DEFAULT_DELAY_BEFORE_REQUEST)
|
||||
val useCaseModule = UseCaseModule(
|
||||
localSourceModule = localSourceModule,
|
||||
networkModule = networkModule
|
||||
)
|
||||
_useCaseModule = useCaseModule
|
||||
_permissionModule = PermissionModule()
|
||||
_viewModelModule = ViewModelModule(useCaseModule)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import androidx.savedstate.SavedStateRegistryOwner
|
|||
import org.fnives.tiktokdownloader.di.module.ViewModelModule
|
||||
import org.fnives.tiktokdownloader.ui.main.MainViewModel
|
||||
import org.fnives.tiktokdownloader.ui.main.queue.QueueViewModel
|
||||
import org.fnives.tiktokdownloader.ui.main.settings.SettingsViewModel
|
||||
|
||||
class ViewModelFactory(
|
||||
savedStateRegistryOwner: SavedStateRegistryOwner,
|
||||
|
|
@ -20,6 +21,7 @@ class ViewModelFactory(
|
|||
val viewModel = when (modelClass) {
|
||||
MainViewModel::class.java -> viewModelModule.mainViewModel(handle)
|
||||
QueueViewModel::class.java -> viewModelModule.queueViewModel
|
||||
SettingsViewModel::class.java -> viewModelModule.settignsViewModel
|
||||
else -> throw IllegalArgumentException("Can't create viewModel for $modelClass ")
|
||||
}
|
||||
return viewModel as T
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import android.content.ContentResolver
|
|||
import android.content.Context
|
||||
import org.fnives.tiktokdownloader.data.local.persistent.SharedPreferencesManager
|
||||
import org.fnives.tiktokdownloader.data.local.persistent.SharedPreferencesManagerImpl
|
||||
import org.fnives.tiktokdownloader.data.local.persistent.UserPreferencesStorage
|
||||
import org.fnives.tiktokdownloader.data.local.save.video.SaveVideoFile
|
||||
import org.fnives.tiktokdownloader.data.local.verify.exists.VerifyFileForUriExists
|
||||
import org.fnives.tiktokdownloader.data.local.verify.exists.VerifyFileForUriExistsImpl
|
||||
import org.fnives.tiktokdownloader.di.ServiceLocator
|
||||
|
||||
class AndroidFileManagementModule(private val context: Context) {
|
||||
private val contentResolver: ContentResolver
|
||||
|
|
@ -16,10 +16,14 @@ class AndroidFileManagementModule(private val context: Context) {
|
|||
val verifyFileForUriExists: VerifyFileForUriExists
|
||||
get() = VerifyFileForUriExistsImpl(contentResolver)
|
||||
|
||||
val sharedPreferencesManager: SharedPreferencesManager by lazy {
|
||||
private val sharedPreferencesManagerImpl by lazy {
|
||||
SharedPreferencesManagerImpl.create(context)
|
||||
}
|
||||
|
||||
val sharedPreferencesManager: SharedPreferencesManager get() = sharedPreferencesManagerImpl
|
||||
|
||||
val userPreferencesStorage: UserPreferencesStorage get() = sharedPreferencesManagerImpl
|
||||
|
||||
private val saveVideoFileFactory: SaveVideoFile.Factory
|
||||
get() = SaveVideoFile.Factory(contentResolver)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.fnives.tiktokdownloader.di.module
|
||||
|
||||
import org.fnives.tiktokdownloader.data.local.CaptchaTimeoutLocalSource
|
||||
import org.fnives.tiktokdownloader.data.local.UserPreferencesLocalSource
|
||||
import org.fnives.tiktokdownloader.data.local.VideoDownloadedLocalSource
|
||||
import org.fnives.tiktokdownloader.data.local.VideoInPendingLocalSource
|
||||
import org.fnives.tiktokdownloader.data.local.VideoInProgressLocalSource
|
||||
|
|
@ -22,6 +23,8 @@ class LocalSourceModule(private val androidFileManagementModule: AndroidFileMana
|
|||
|
||||
val videoInProgressLocalSource: VideoInProgressLocalSource by lazy { VideoInProgressLocalSource() }
|
||||
|
||||
val userPreferencesLocalSource: UserPreferencesLocalSource by lazy{ UserPreferencesLocalSource(androidFileManagementModule.userPreferencesStorage)}
|
||||
|
||||
val captchaTimeoutLocalSource: CaptchaTimeoutLocalSource
|
||||
get() = CaptchaTimeoutLocalSource(
|
||||
androidFileManagementModule.sharedPreferencesManager,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
package org.fnives.tiktokdownloader.di.module
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import org.fnives.tiktokdownloader.data.local.persistent.UserPreferencesStorage
|
||||
import org.fnives.tiktokdownloader.data.usecase.AddVideoToQueueUseCase
|
||||
import org.fnives.tiktokdownloader.data.usecase.GetUserPreferences
|
||||
import org.fnives.tiktokdownloader.data.usecase.ObserveUserPreferences
|
||||
import org.fnives.tiktokdownloader.data.usecase.MoveVideoInQueueUseCase
|
||||
import org.fnives.tiktokdownloader.data.usecase.RemoveVideoFromQueueUseCase
|
||||
import org.fnives.tiktokdownloader.data.usecase.SetUserPreferences
|
||||
import org.fnives.tiktokdownloader.data.usecase.StateOfVideosObservableUseCase
|
||||
import org.fnives.tiktokdownloader.data.usecase.UrlVerificationUseCase
|
||||
import org.fnives.tiktokdownloader.data.usecase.VideoDownloadingProcessorUseCase
|
||||
|
|
@ -41,6 +45,10 @@ class UseCaseModule(
|
|||
localSourceModule.videoInPendingLocalSource
|
||||
)
|
||||
|
||||
val getUserPreferences: GetUserPreferences get() = GetUserPreferences(localSourceModule.userPreferencesLocalSource)
|
||||
val observeUserPreferences: ObserveUserPreferences get() = ObserveUserPreferences(localSourceModule.userPreferencesLocalSource)
|
||||
val setUserPreferences: SetUserPreferences get() = SetUserPreferences(localSourceModule.userPreferencesLocalSource)
|
||||
|
||||
val videoDownloadingProcessorUseCase: VideoDownloadingProcessorUseCase by lazy {
|
||||
VideoDownloadingProcessorUseCase(
|
||||
tikTokDownloadRemoteSource = networkModule.tikTokDownloadRemoteSource,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.fnives.tiktokdownloader.di.module
|
|||
import androidx.lifecycle.SavedStateHandle
|
||||
import org.fnives.tiktokdownloader.ui.main.MainViewModel
|
||||
import org.fnives.tiktokdownloader.ui.main.queue.QueueViewModel
|
||||
import org.fnives.tiktokdownloader.ui.main.settings.SettingsViewModel
|
||||
import org.fnives.tiktokdownloader.ui.service.QueueServiceViewModel
|
||||
|
||||
class ViewModelModule(private val useCaseModule: UseCaseModule) {
|
||||
|
|
@ -28,4 +29,10 @@ class ViewModelModule(private val useCaseModule: UseCaseModule) {
|
|||
useCaseModule.videoDownloadingProcessorUseCase,
|
||||
useCaseModule.moveVideoInQueueUseCase
|
||||
)
|
||||
|
||||
val settignsViewModel: SettingsViewModel get() =
|
||||
SettingsViewModel(
|
||||
useCaseModule.observeUserPreferences,
|
||||
useCaseModule.setUserPreferences
|
||||
)
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ import org.fnives.tiktokdownloader.di.ServiceLocator
|
|||
import org.fnives.tiktokdownloader.di.provideViewModels
|
||||
import org.fnives.tiktokdownloader.ui.main.help.HelpFragment
|
||||
import org.fnives.tiktokdownloader.ui.main.queue.QueueFragment
|
||||
import org.fnives.tiktokdownloader.ui.main.settings.SettingsFragment
|
||||
import org.fnives.tiktokdownloader.ui.permission.PermissionRequester
|
||||
import org.fnives.tiktokdownloader.ui.service.QueueService
|
||||
|
||||
|
|
@ -57,6 +58,7 @@ class MainActivity : AppCompatActivity() {
|
|||
bottomNavigationView.setOnItemSelectedListener { item ->
|
||||
val fragment = when (item.itemId) {
|
||||
R.id.help_menu_item -> HelpFragment.newInstance()
|
||||
R.id.settings_menu_item -> SettingsFragment.newInstance()
|
||||
R.id.queue_menu_item -> QueueFragment.newInstance()
|
||||
else -> return@setOnItemSelectedListener false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
package org.fnives.tiktokdownloader.ui.main.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.SwitchCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import org.fnives.tiktokdownloader.R
|
||||
import org.fnives.tiktokdownloader.di.provideViewModels
|
||||
|
||||
class SettingsFragment : Fragment(R.layout.fragment_settings) {
|
||||
|
||||
private val viewModel by provideViewModels<SettingsViewModel>()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val alwaysOpenAppHolder = view.findViewById<View>(R.id.always_open_app_holder)
|
||||
val alwaysOpenAppSwitch = view.findViewById<SwitchCompat>(R.id.always_open_app)
|
||||
viewModel.userPreferences.observe(viewLifecycleOwner) {
|
||||
alwaysOpenAppSwitch.isChecked = it.alwaysOpenApp
|
||||
}
|
||||
alwaysOpenAppSwitch.setOnCheckedChangeListener { _, isChecked ->
|
||||
viewModel.setAlwaysOpenApp(isChecked)
|
||||
}
|
||||
alwaysOpenAppHolder.setOnClickListener {
|
||||
viewModel.setAlwaysOpenApp(!alwaysOpenAppSwitch.isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): SettingsFragment = SettingsFragment()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package org.fnives.tiktokdownloader.ui.main.settings
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.fnives.tiktokdownloader.data.usecase.ObserveUserPreferences
|
||||
import org.fnives.tiktokdownloader.data.usecase.SetUserPreferences
|
||||
import org.fnives.tiktokdownloader.ui.shared.asLiveData
|
||||
|
||||
class SettingsViewModel(
|
||||
private val getUserPreferences: ObserveUserPreferences,
|
||||
private val setUserPreferences: SetUserPreferences
|
||||
) : ViewModel() {
|
||||
|
||||
val userPreferences = asLiveData(getUserPreferences.invoke())
|
||||
|
||||
fun setAlwaysOpenApp(alwaysOpenApp: Boolean) {
|
||||
val userPreferences = userPreferences.value ?: return
|
||||
if (userPreferences.alwaysOpenApp == alwaysOpenApp) return
|
||||
|
||||
viewModelScope.launch {
|
||||
setUserPreferences(userPreferences.copy(alwaysOpenApp = alwaysOpenApp))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package org.fnives.tiktokdownloader.ui.service
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import org.fnives.tiktokdownloader.data.usecase.GetUserPreferences
|
||||
import org.fnives.tiktokdownloader.di.ServiceLocator
|
||||
import org.fnives.tiktokdownloader.ui.main.MainActivity
|
||||
import org.fnives.tiktokdownloader.ui.permission.PermissionRequester
|
||||
|
|
@ -12,16 +13,31 @@ class DownloadIntentReceiverActivity : AppCompatActivity() {
|
|||
private val permissionRequester: PermissionRequester by lazy {
|
||||
ServiceLocator.permissionModule.permissionRequester
|
||||
}
|
||||
private val getUserPreferences: GetUserPreferences by lazy {
|
||||
ServiceLocator.useCaseModule.getUserPreferences
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
intent.getStringExtra(Intent.EXTRA_TEXT)?.let { url ->
|
||||
if (getUserPreferences().alwaysOpenApp) {
|
||||
alwaysOpen(url)
|
||||
} else {
|
||||
openOnlyIfNeeded(url)
|
||||
}
|
||||
}
|
||||
super.onCreate(savedInstanceState)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun alwaysOpen(url: String) {
|
||||
startActivity(MainActivity.buildIntent(this, url))
|
||||
}
|
||||
|
||||
private fun openOnlyIfNeeded(url: String) {
|
||||
if (permissionRequester.isGranted(this)) {
|
||||
startService(QueueService.buildIntent(this, url))
|
||||
} else {
|
||||
startActivity(MainActivity.buildIntent(this, url))
|
||||
}
|
||||
}
|
||||
super.onCreate(savedInstanceState)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
8
app/src/main/res/drawable/ic_twotone_settings.xml
Normal file
8
app/src/main/res/drawable/ic_twotone_settings.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillAlpha="0.3"
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19.28,8.6l-0.7,-1.21 -1.27,0.51 -1.06,0.43 -0.91,-0.7c-0.39,-0.3 -0.8,-0.54 -1.23,-0.71l-1.06,-0.43 -0.16,-1.13L12.7,4h-1.4l-0.19,1.35 -0.16,1.13 -1.06,0.44c-0.41,0.17 -0.82,0.41 -1.25,0.73l-0.9,0.68 -1.05,-0.42 -1.27,-0.52 -0.7,1.21 1.08,0.84 0.89,0.7 -0.14,1.13c-0.03,0.3 -0.05,0.53 -0.05,0.73s0.02,0.43 0.05,0.73l0.14,1.13 -0.89,0.7 -1.08,0.84 0.7,1.21 1.27,-0.51 1.06,-0.43 0.91,0.7c0.39,0.3 0.8,0.54 1.23,0.71l1.06,0.43 0.16,1.13 0.19,1.36h1.39l0.19,-1.35 0.16,-1.13 1.06,-0.43c0.41,-0.17 0.82,-0.41 1.25,-0.73l0.9,-0.68 1.04,0.42 1.27,0.51 0.7,-1.21 -1.08,-0.84 -0.89,-0.7 0.14,-1.13c0.04,-0.31 0.05,-0.52 0.05,-0.73 0,-0.21 -0.02,-0.43 -0.05,-0.73l-0.14,-1.13 0.89,-0.7 1.1,-0.84zM12,16c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z" android:strokeAlpha="0.3"/>
|
||||
<path android:fillColor="@android:color/white" android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98 0,-0.34 -0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.09,-0.16 -0.26,-0.25 -0.44,-0.25 -0.06,0 -0.12,0.01 -0.17,0.03l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.06,-0.02 -0.12,-0.03 -0.18,-0.03 -0.17,0 -0.34,0.09 -0.43,0.25l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.09,0.16 0.26,0.25 0.44,0.25 0.06,0 0.12,-0.01 0.17,-0.03l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.06,0.02 0.12,0.03 0.18,0.03 0.17,0 0.34,-0.09 0.43,-0.25l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM17.45,11.27c0.04,0.31 0.05,0.52 0.05,0.73 0,0.21 -0.02,0.43 -0.05,0.73l-0.14,1.13 0.89,0.7 1.08,0.84 -0.7,1.21 -1.27,-0.51 -1.04,-0.42 -0.9,0.68c-0.43,0.32 -0.84,0.56 -1.25,0.73l-1.06,0.43 -0.16,1.13 -0.2,1.35h-1.4l-0.19,-1.35 -0.16,-1.13 -1.06,-0.43c-0.43,-0.18 -0.83,-0.41 -1.23,-0.71l-0.91,-0.7 -1.06,0.43 -1.27,0.51 -0.7,-1.21 1.08,-0.84 0.89,-0.7 -0.14,-1.13c-0.03,-0.31 -0.05,-0.54 -0.05,-0.74s0.02,-0.43 0.05,-0.73l0.14,-1.13 -0.89,-0.7 -1.08,-0.84 0.7,-1.21 1.27,0.51 1.04,0.42 0.9,-0.68c0.43,-0.32 0.84,-0.56 1.25,-0.73l1.06,-0.43 0.16,-1.13 0.2,-1.35h1.39l0.19,1.35 0.16,1.13 1.06,0.43c0.43,0.18 0.83,0.41 1.23,0.71l0.91,0.7 1.06,-0.43 1.27,-0.51 0.7,1.21 -1.07,0.85 -0.89,0.7 0.14,1.13zM12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM12,14c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
|
||||
</vector>
|
||||
46
app/src/main/res/layout/fragment_settings.xml
Normal file
46
app/src/main/res/layout/fragment_settings.xml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/activity_horizontal_margin">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings"
|
||||
android:textAppearance="?attr/textAppearanceHeadline5" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/default_padding"
|
||||
app:cardCornerRadius="@dimen/card_corner_radius"
|
||||
app:cardElevation="@dimen/card_elevation">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/always_open_app_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/default_padding">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/user_preference_always_open_app"
|
||||
android:textAppearance="?attr/textAppearanceSubtitle1" />
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/always_open_app"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -6,6 +6,11 @@
|
|||
android:icon="@drawable/ic_download"
|
||||
android:title="@string/queue" />
|
||||
|
||||
<item
|
||||
android:id="@+id/settings_menu_item"
|
||||
android:icon="@drawable/ic_twotone_settings"
|
||||
android:title="@string/settings" />
|
||||
|
||||
<item
|
||||
android:id="@+id/help_menu_item"
|
||||
android:icon="@drawable/ic_twotone_help"
|
||||
|
|
|
|||
|
|
@ -47,4 +47,6 @@
|
|||
<string name="captcha_handling">It\'s possible if you try to download too many videos at the same time <b>captcha</b> will be triggered. Since we don\'t want to overload the server, in such case you will need to wait a couple hours to properly retry the download. If that still doesn\'t work you may need to verify a captcha on the same network.</string>
|
||||
<string name="link_to_repository">This is an open source project. You can see the repository clicking <u>here.</u></string>
|
||||
<string name="could_not_open">Couldn\'t open!</string>
|
||||
<string name="settings">Settings</string>
|
||||
<string name="user_preference_always_open_app">Always open app when sharing video</string>
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue