Merge pull request #3511 from wb9688/ktlint

Ktlint
This commit is contained in:
wb9688 2020-05-04 15:13:07 +02:00 committed by GitHub
commit b630f269c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 402 additions and 290 deletions

View File

@ -116,25 +116,40 @@ task runCheckstyle(type: Checkstyle) {
}
}
tasks.withType(Checkstyle).each {
checkstyleTask -> checkstyleTask.doLast {
reports.all { report ->
def outputFile = report.destination
if (outputFile.exists() && outputFile.text.contains("severity=\"error\"")) {
throw new GradleException("There were checkstyle errors! For more info check $outputFile")
}
runCheckstyle.doLast {
reports.all { report ->
def outputFile = report.destination
if (outputFile.exists() && outputFile.text.contains("severity=\"error\"")) {
throw new GradleException("There were checkstyle errors! For more info check $outputFile")
}
}
}
configurations {
ktlint
}
task runKtlint(type: JavaExec) {
main = "com.pinterest.ktlint.Main"
classpath = configurations.ktlint
args "src/**/*.kt"
}
task formatKtlint(type: JavaExec) {
main = "com.pinterest.ktlint.Main"
classpath = configurations.ktlint
args "-F", "src/**/*.kt"
}
afterEvaluate {
preDebugBuild.dependsOn runCheckstyle
preDebugBuild.dependsOn runCheckstyle, runKtlint
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
debugImplementation "com.puppycrawl.tools:checkstyle:${checkstyleVersion}"
ktlint "com.pinterest:ktlint:0.35.0"
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation "android.arch.persistence.room:testing:1.1.1"

View File

@ -116,4 +116,4 @@ class AppDatabaseTest {
testHelper.closeWhenFinished(database)
return database
}
}
}

View File

@ -43,15 +43,15 @@ import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.AndroidTvUtils;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.AndroidTvUtils;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.views.FocusOverlayView;
import org.schabi.newpipe.util.urlfinder.UrlFinder;
import org.schabi.newpipe.views.FocusOverlayView;
import java.io.Serializable;
import java.util.ArrayList;

View File

@ -1,12 +1,17 @@
package org.schabi.newpipe.database.feed.dao
import androidx.room.*
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Update
import io.reactivex.Flowable
import java.util.Date
import org.schabi.newpipe.database.feed.model.FeedEntity
import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.database.subscription.SubscriptionEntity
import java.util.*
@Dao
abstract class FeedDAO {

View File

@ -1,6 +1,11 @@
package org.schabi.newpipe.database.feed.dao
import androidx.room.*
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Update
import io.reactivex.Flowable
import io.reactivex.Maybe
import org.schabi.newpipe.database.feed.model.FeedGroupEntity

View File

@ -27,11 +27,11 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity
]
)
data class FeedEntity(
@ColumnInfo(name = STREAM_ID)
var streamId: Long,
@ColumnInfo(name = STREAM_ID)
var streamId: Long,
@ColumnInfo(name = SUBSCRIPTION_ID)
var subscriptionId: Long
@ColumnInfo(name = SUBSCRIPTION_ID)
var subscriptionId: Long
) {
companion object {
@ -40,4 +40,4 @@ data class FeedEntity(
const val STREAM_ID = "stream_id"
const val SUBSCRIPTION_ID = "subscription_id"
}
}
}

View File

@ -13,18 +13,18 @@ import org.schabi.newpipe.local.subscription.FeedGroupIcon
indices = [Index(SORT_ORDER)]
)
data class FeedGroupEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ID)
val uid: Long,
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = ID)
val uid: Long,
@ColumnInfo(name = NAME)
var name: String,
@ColumnInfo(name = NAME)
var name: String,
@ColumnInfo(name = ICON)
var icon: FeedGroupIcon,
@ColumnInfo(name = ICON)
var icon: FeedGroupIcon,
@ColumnInfo(name = SORT_ORDER)
var sortOrder: Long = -1
@ColumnInfo(name = SORT_ORDER)
var sortOrder: Long = -1
) {
companion object {
const val FEED_GROUP_TABLE = "feed_group"
@ -36,4 +36,4 @@ data class FeedGroupEntity(
const val GROUP_ALL_ID = -1L
}
}
}

View File

@ -29,11 +29,11 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity
]
)
data class FeedGroupSubscriptionEntity(
@ColumnInfo(name = GROUP_ID)
var feedGroupId: Long,
@ColumnInfo(name = GROUP_ID)
var feedGroupId: Long,
@ColumnInfo(name = SUBSCRIPTION_ID)
var subscriptionId: Long
@ColumnInfo(name = SUBSCRIPTION_ID)
var subscriptionId: Long
) {
companion object {
@ -42,4 +42,4 @@ data class FeedGroupSubscriptionEntity(
const val GROUP_ID = "group_id"
const val SUBSCRIPTION_ID = "subscription_id"
}
}
}

View File

@ -4,10 +4,10 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
import java.util.Date
import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity.Companion.FEED_LAST_UPDATED_TABLE
import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity.Companion.SUBSCRIPTION_ID
import org.schabi.newpipe.database.subscription.SubscriptionEntity
import java.util.*
@Entity(
tableName = FEED_LAST_UPDATED_TABLE,
@ -20,12 +20,12 @@ import java.util.*
]
)
data class FeedLastUpdatedEntity(
@PrimaryKey
@ColumnInfo(name = SUBSCRIPTION_ID)
var subscriptionId: Long,
@PrimaryKey
@ColumnInfo(name = SUBSCRIPTION_ID)
var subscriptionId: Long,
@ColumnInfo(name = LAST_UPDATED)
var lastUpdated: Date? = null
@ColumnInfo(name = LAST_UPDATED)
var lastUpdated: Date? = null
) {
companion object {
@ -34,4 +34,4 @@ data class FeedLastUpdatedEntity(
const val SUBSCRIPTION_ID = "subscription_id"
const val LAST_UPDATED = "last_updated"
}
}
}

View File

@ -2,21 +2,21 @@ package org.schabi.newpipe.database.history.model
import androidx.room.ColumnInfo
import androidx.room.Embedded
import java.util.Date
import org.schabi.newpipe.database.stream.model.StreamEntity
import java.util.*
data class StreamHistoryEntry(
@Embedded
val streamEntity: StreamEntity,
@Embedded
val streamEntity: StreamEntity,
@ColumnInfo(name = StreamHistoryEntity.JOIN_STREAM_ID)
val streamId: Long,
@ColumnInfo(name = StreamHistoryEntity.JOIN_STREAM_ID)
val streamId: Long,
@ColumnInfo(name = StreamHistoryEntity.STREAM_ACCESS_DATE)
val accessDate: Date,
@ColumnInfo(name = StreamHistoryEntity.STREAM_ACCESS_DATE)
val accessDate: Date,
@ColumnInfo(name = StreamHistoryEntity.STREAM_REPEAT_COUNT)
val repeatCount: Long
@ColumnInfo(name = StreamHistoryEntity.STREAM_REPEAT_COUNT)
val repeatCount: Long
) {
fun toStreamHistoryEntity(): StreamHistoryEntity {

View File

@ -8,14 +8,14 @@ import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.extractor.stream.StreamInfoItem
class PlaylistStreamEntry(
@Embedded
val streamEntity: StreamEntity,
@Embedded
val streamEntity: StreamEntity,
@ColumnInfo(name = PlaylistStreamEntity.JOIN_STREAM_ID)
val streamId: Long,
@ColumnInfo(name = PlaylistStreamEntity.JOIN_STREAM_ID)
val streamId: Long,
@ColumnInfo(name = PlaylistStreamEntity.JOIN_INDEX)
val joinIndex: Int
@ColumnInfo(name = PlaylistStreamEntity.JOIN_INDEX)
val joinIndex: Int
) : LocalItem {
@Throws(IllegalArgumentException::class)

View File

@ -2,24 +2,24 @@ package org.schabi.newpipe.database.stream
import androidx.room.ColumnInfo
import androidx.room.Embedded
import java.util.Date
import org.schabi.newpipe.database.LocalItem
import org.schabi.newpipe.database.history.model.StreamHistoryEntity
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import java.util.*
class StreamStatisticsEntry(
@Embedded
val streamEntity: StreamEntity,
@Embedded
val streamEntity: StreamEntity,
@ColumnInfo(name = StreamHistoryEntity.JOIN_STREAM_ID)
val streamId: Long,
@ColumnInfo(name = StreamHistoryEntity.JOIN_STREAM_ID)
val streamId: Long,
@ColumnInfo(name = STREAM_LATEST_DATE)
val latestAccessDate: Date,
@ColumnInfo(name = STREAM_LATEST_DATE)
val latestAccessDate: Date,
@ColumnInfo(name = STREAM_WATCH_COUNT)
val watchCount: Long
@ColumnInfo(name = STREAM_WATCH_COUNT)
val watchCount: Long
) : LocalItem {
fun toStreamInfoItem(): StreamInfoItem {

View File

@ -1,15 +1,19 @@
package org.schabi.newpipe.database.stream.dao
import androidx.room.*
import androidx.room.ColumnInfo
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import io.reactivex.Flowable
import java.util.Date
import org.schabi.newpipe.database.BasicDAO
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_ID
import org.schabi.newpipe.extractor.stream.StreamType
import org.schabi.newpipe.extractor.stream.StreamType.AUDIO_LIVE_STREAM
import org.schabi.newpipe.extractor.stream.StreamType.LIVE_STREAM
import java.util.*
import kotlin.collections.ArrayList
@Dao
abstract class StreamDAO : BasicDAO<StreamEntity> {
@ -94,7 +98,6 @@ abstract class StreamDAO : BasicDAO<StreamEntity> {
if (existentMinimalStream.duration > 0 && newerStream.duration < 0) {
newerStream.duration = existentMinimalStream.duration
}
}
}
@ -116,21 +119,22 @@ abstract class StreamDAO : BasicDAO<StreamEntity> {
* Minimal entry class used when comparing/updating an existent stream.
*/
internal data class StreamCompareFeed(
@ColumnInfo(name = STREAM_ID)
var uid: Long = 0,
@ColumnInfo(name = STREAM_ID)
var uid: Long = 0,
@ColumnInfo(name = StreamEntity.STREAM_TYPE)
var streamType: StreamType,
@ColumnInfo(name = StreamEntity.STREAM_TYPE)
var streamType: StreamType,
@ColumnInfo(name = StreamEntity.STREAM_TEXTUAL_UPLOAD_DATE)
var textualUploadDate: String? = null,
@ColumnInfo(name = StreamEntity.STREAM_TEXTUAL_UPLOAD_DATE)
var textualUploadDate: String? = null,
@ColumnInfo(name = StreamEntity.STREAM_UPLOAD_DATE)
var uploadDate: Date? = null,
@ColumnInfo(name = StreamEntity.STREAM_UPLOAD_DATE)
var uploadDate: Date? = null,
@ColumnInfo(name = StreamEntity.STREAM_IS_UPLOAD_DATE_APPROXIMATION)
var isUploadDateApproximation: Boolean? = null,
@ColumnInfo(name = StreamEntity.STREAM_IS_UPLOAD_DATE_APPROXIMATION)
var isUploadDateApproximation: Boolean? = null,
@ColumnInfo(name = StreamEntity.STREAM_DURATION)
var duration: Long)
@ColumnInfo(name = StreamEntity.STREAM_DURATION)
var duration: Long
)
}

View File

@ -1,6 +1,13 @@
package org.schabi.newpipe.database.stream.model
import androidx.room.*
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.Index
import androidx.room.PrimaryKey
import java.io.Serializable
import java.util.Calendar
import java.util.Date
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_SERVICE_ID
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_TABLE
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_URL
@ -9,8 +16,6 @@ import org.schabi.newpipe.extractor.stream.StreamInfo
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.extractor.stream.StreamType
import org.schabi.newpipe.player.playqueue.PlayQueueItem
import java.io.Serializable
import java.util.*
@Entity(tableName = STREAM_TABLE,
indices = [
@ -18,42 +23,42 @@ import java.util.*
]
)
data class StreamEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = STREAM_ID)
var uid: Long = 0,
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = STREAM_ID)
var uid: Long = 0,
@ColumnInfo(name = STREAM_SERVICE_ID)
var serviceId: Int,
@ColumnInfo(name = STREAM_SERVICE_ID)
var serviceId: Int,
@ColumnInfo(name = STREAM_URL)
var url: String,
@ColumnInfo(name = STREAM_URL)
var url: String,
@ColumnInfo(name = STREAM_TITLE)
var title: String,
@ColumnInfo(name = STREAM_TITLE)
var title: String,
@ColumnInfo(name = STREAM_TYPE)
var streamType: StreamType,
@ColumnInfo(name = STREAM_TYPE)
var streamType: StreamType,
@ColumnInfo(name = STREAM_DURATION)
var duration: Long,
@ColumnInfo(name = STREAM_DURATION)
var duration: Long,
@ColumnInfo(name = STREAM_UPLOADER)
var uploader: String,
@ColumnInfo(name = STREAM_UPLOADER)
var uploader: String,
@ColumnInfo(name = STREAM_THUMBNAIL_URL)
var thumbnailUrl: String? = null,
@ColumnInfo(name = STREAM_THUMBNAIL_URL)
var thumbnailUrl: String? = null,
@ColumnInfo(name = STREAM_VIEWS)
var viewCount: Long? = null,
@ColumnInfo(name = STREAM_VIEWS)
var viewCount: Long? = null,
@ColumnInfo(name = STREAM_TEXTUAL_UPLOAD_DATE)
var textualUploadDate: String? = null,
@ColumnInfo(name = STREAM_TEXTUAL_UPLOAD_DATE)
var textualUploadDate: String? = null,
@ColumnInfo(name = STREAM_UPLOAD_DATE)
var uploadDate: Date? = null,
@ColumnInfo(name = STREAM_UPLOAD_DATE)
var uploadDate: Date? = null,
@ColumnInfo(name = STREAM_IS_UPLOAD_DATE_APPROXIMATION)
var isUploadDateApproximation: Boolean? = null
@ColumnInfo(name = STREAM_IS_UPLOAD_DATE_APPROXIMATION)
var isUploadDateApproximation: Boolean? = null
) : Serializable {
@Ignore

View File

@ -1,6 +1,10 @@
package org.schabi.newpipe.database.subscription
import androidx.room.*
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import io.reactivex.Flowable
import io.reactivex.Maybe
import org.schabi.newpipe.database.BasicDAO

View File

@ -41,12 +41,12 @@ import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.search.SearchInfo;
import org.schabi.newpipe.util.AndroidTvUtils;
import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.list.BaseListFragment;
import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.AndroidTvUtils;
import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.ExtractorHelper;

View File

@ -7,6 +7,8 @@ import io.reactivex.Flowable
import io.reactivex.Maybe
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.util.Calendar
import java.util.Date
import org.schabi.newpipe.MainActivity.DEBUG
import org.schabi.newpipe.NewPipeDatabase
import org.schabi.newpipe.database.feed.model.FeedEntity
@ -16,8 +18,6 @@ import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.extractor.stream.StreamType
import org.schabi.newpipe.local.subscription.FeedGroupIcon
import java.util.*
import kotlin.collections.ArrayList
class FeedDatabaseManager(context: Context) {
private val database = NewPipeDatabase.getInstance(context)
@ -70,8 +70,11 @@ class FeedDatabaseManager(context: Context) {
fun markAsOutdated(subscriptionId: Long) = feedTable
.setLastUpdatedForSubscription(FeedLastUpdatedEntity(subscriptionId, null))
fun upsertAll(subscriptionId: Long, items: List<StreamInfoItem>,
oldestAllowedDate: Date = FEED_OLDEST_ALLOWED_DATE.time) {
fun upsertAll(
subscriptionId: Long,
items: List<StreamInfoItem>,
oldestAllowedDate: Date = FEED_OLDEST_ALLOWED_DATE.time
) {
val itemsToInsert = ArrayList<StreamInfoItem>()
loop@ for (streamItem in items) {
val uploadDate = streamItem.uploadDate
@ -107,9 +110,9 @@ class FeedDatabaseManager(context: Context) {
if (DEBUG) Log.d(this::class.java.simpleName, "clear() → streamTable.deleteOrphans() → $deletedOrphans")
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Feed Groups
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
fun subscriptionIdsForGroup(groupId: Long): Flowable<List<Long>> {
return feedGroupTable.getSubscriptionIdsFor(groupId)
@ -161,6 +164,5 @@ class FeedDatabaseManager(context: Context) {
FeedGroupEntity.GROUP_ALL_ID -> feedTable.oldestSubscriptionUpdateFromAll()
else -> feedTable.oldestSubscriptionUpdate(groupId)
}
}
}

View File

@ -22,14 +22,28 @@ package org.schabi.newpipe.local.feed
import android.content.Intent
import android.os.Bundle
import android.os.Parcelable
import android.view.*
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.preference.PreferenceManager
import icepick.State
import kotlinx.android.synthetic.main.error_retry.*
import kotlinx.android.synthetic.main.fragment_feed.*
import java.util.Calendar
import kotlinx.android.synthetic.main.error_retry.error_button_retry
import kotlinx.android.synthetic.main.error_retry.error_message_view
import kotlinx.android.synthetic.main.fragment_feed.empty_state_view
import kotlinx.android.synthetic.main.fragment_feed.error_panel
import kotlinx.android.synthetic.main.fragment_feed.items_list
import kotlinx.android.synthetic.main.fragment_feed.loading_progress_bar
import kotlinx.android.synthetic.main.fragment_feed.loading_progress_text
import kotlinx.android.synthetic.main.fragment_feed.refresh_root_view
import kotlinx.android.synthetic.main.fragment_feed.refresh_subtitle_text
import kotlinx.android.synthetic.main.fragment_feed.refresh_text
import org.schabi.newpipe.R
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
import org.schabi.newpipe.fragments.list.BaseListFragment
@ -37,7 +51,6 @@ import org.schabi.newpipe.local.feed.service.FeedLoadService
import org.schabi.newpipe.report.UserAction
import org.schabi.newpipe.util.AnimationUtils.animateView
import org.schabi.newpipe.util.Localization
import java.util.*
class FeedFragment : BaseListFragment<FeedState, Unit>() {
private lateinit var viewModel: FeedViewModel
@ -98,9 +111,9 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
}
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Menu
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
@ -150,9 +163,9 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
activity?.supportActionBar?.subtitle = null
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Handling
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
override fun showLoading() {
animateView(refresh_root_view, false, 0)
@ -259,7 +272,6 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
}
}
private fun handleErrorState(errorState: FeedState.ErrorState): Boolean {
hideLoading()
errorState.error?.let {
@ -283,9 +295,9 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
refresh_text?.text = getString(R.string.feed_oldest_subscription_update, oldestSubscriptionUpdateText)
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Load Service Handling
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
override fun doInitialLoadLogic() {}
override fun reloadContent() = triggerUpdate()

View File

@ -1,24 +1,24 @@
package org.schabi.newpipe.local.feed
import androidx.annotation.StringRes
import java.util.Calendar
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import java.util.*
sealed class FeedState {
data class ProgressState(
val currentProgress: Int = -1,
val maxProgress: Int = -1,
@StringRes val progressMessage: Int = 0
val currentProgress: Int = -1,
val maxProgress: Int = -1,
@StringRes val progressMessage: Int = 0
) : FeedState()
data class LoadedState(
val items: List<StreamInfoItem>,
val oldestUpdate: Calendar? = null,
val notLoadedCount: Long,
val itemsErrors: List<Throwable> = emptyList()
val items: List<StreamInfoItem>,
val oldestUpdate: Calendar? = null,
val notLoadedCount: Long,
val itemsErrors: List<Throwable> = emptyList()
) : FeedState()
data class ErrorState(
val error: Throwable? = null
val error: Throwable? = null
) : FeedState()
}
}

View File

@ -9,13 +9,17 @@ import io.reactivex.Flowable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Function4
import io.reactivex.schedulers.Schedulers
import java.util.Calendar
import java.util.Date
import java.util.concurrent.TimeUnit
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.local.feed.service.FeedEventManager
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.*
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ErrorResultEvent
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.IdleEvent
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ProgressEvent
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.SuccessResultEvent
import org.schabi.newpipe.util.DEFAULT_THROTTLE_TIMEOUT
import java.util.*
import java.util.concurrent.TimeUnit
class FeedViewModel(applicationContext: Context, val groupId: Long = FeedGroupEntity.GROUP_ALL_ID) : ViewModel() {
class Factory(val context: Context, val groupId: Long = FeedGroupEntity.GROUP_ALL_ID) : ViewModelProvider.Factory {
@ -68,4 +72,4 @@ class FeedViewModel(applicationContext: Context, val groupId: Long = FeedGroupEn
}
private data class CombineResultHolder(val t1: FeedEventManager.Event, val t2: List<StreamInfoItem>, val t3: Long, val t4: Date?)
}
}

View File

@ -3,8 +3,8 @@ package org.schabi.newpipe.local.feed.service
import androidx.annotation.StringRes
import io.reactivex.Flowable
import io.reactivex.processors.BehaviorProcessor
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.IdleEvent
import java.util.concurrent.atomic.AtomicBoolean
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.IdleEvent
object FeedEventManager {
private var processor: BehaviorProcessor<Event> = BehaviorProcessor.create()
@ -34,5 +34,4 @@ object FeedEventManager {
data class SuccessResultEvent(val itemsErrors: List<Throwable> = emptyList()) : Event()
data class ErrorResultEvent(val error: Throwable) : Event()
}
}

View File

@ -40,6 +40,11 @@ import io.reactivex.functions.Consumer
import io.reactivex.functions.Function
import io.reactivex.processors.PublishProcessor
import io.reactivex.schedulers.Schedulers
import java.io.IOException
import java.util.Calendar
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
import org.reactivestreams.Subscriber
import org.reactivestreams.Subscription
import org.schabi.newpipe.MainActivity.DEBUG
@ -49,17 +54,14 @@ import org.schabi.newpipe.extractor.ListInfo
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.local.feed.FeedDatabaseManager
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.*
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ErrorResultEvent
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.IdleEvent
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ProgressEvent
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.SuccessResultEvent
import org.schabi.newpipe.local.feed.service.FeedEventManager.postEvent
import org.schabi.newpipe.local.subscription.SubscriptionManager
import org.schabi.newpipe.util.ExceptionUtils
import org.schabi.newpipe.util.ExtractorHelper
import java.io.IOException
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
import kotlin.collections.ArrayList
class FeedLoadService : Service() {
companion object {
@ -94,9 +96,9 @@ class FeedLoadService : Service() {
private var disposables = CompositeDisposable()
private var notificationUpdater = PublishProcessor.create<String>()
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
override fun onCreate() {
super.onCreate()
@ -151,9 +153,9 @@ class FeedLoadService : Service() {
return null
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Loading & Handling
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
private class RequestException(val subscriptionId: Long, message: String, cause: Throwable) : Exception(message, cause) {
companion object {
@ -312,7 +314,6 @@ class FeedLoadService : Service() {
feedResultsHolder.addErrors(RequestException.wrapList(subscriptionId, info))
feedDatabaseManager.markAsOutdated(subscriptionId)
}
} else if (notification.isOnError) {
val error = notification.error!!
feedResultsHolder.addError(error)
@ -325,7 +326,6 @@ class FeedLoadService : Service() {
}
}
private val errorHandlingConsumer: Consumer<Notification<Pair<Long, ListInfo<StreamInfoItem>>>>
get() = Consumer {
if (it.isOnError) {
@ -354,9 +354,9 @@ class FeedLoadService : Service() {
broadcastProgress()
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Notification
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
private lateinit var notificationManager: NotificationManagerCompat
private lateinit var notificationBuilder: NotificationCompat.Builder
@ -412,9 +412,9 @@ class FeedLoadService : Service() {
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build())
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Notification Actions
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
private lateinit var broadcastReceiver: BroadcastReceiver
private val cancelSignal = AtomicBoolean()
@ -430,18 +430,18 @@ class FeedLoadService : Service() {
registerReceiver(broadcastReceiver, IntentFilter(ACTION_CANCEL))
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Error handling
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
private fun handleError(error: Throwable) {
postEvent(ErrorResultEvent(error))
stopService()
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Results Holder
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
class ResultsHolder {
/**
@ -463,4 +463,4 @@ class FeedLoadService : Service() {
itemsErrors = itemsErrorsHolder.toList()
}
}
}
}

View File

@ -7,15 +7,15 @@ import org.schabi.newpipe.R
import org.schabi.newpipe.util.ThemeHelper
enum class FeedGroupIcon(
/**
* The id that will be used to store and retrieve icons from some persistent storage (e.g. DB).
*/
val id: Int,
/**
* The id that will be used to store and retrieve icons from some persistent storage (e.g. DB).
*/
val id: Int,
/**
* The attribute that points to a drawable resource. "R.attr" is used here to support multiple themes.
*/
@AttrRes val drawableResourceAttr: Int
/**
* The attribute that points to a drawable resource. "R.attr" is used here to support multiple themes.
*/
@AttrRes val drawableResourceAttr: Int
) {
ALL(0, R.attr.ic_asterisk),
MUSIC(1, R.attr.ic_music_note),
@ -60,4 +60,4 @@ enum class FeedGroupIcon(
fun getDrawableRes(context: Context): Int {
return ThemeHelper.resolveResourceIdFromAttr(context, drawableResourceAttr)
}
}
}

View File

@ -2,13 +2,21 @@ package org.schabi.newpipe.local.subscription
import android.app.Activity
import android.app.AlertDialog
import android.content.*
import android.content.BroadcastReceiver
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Configuration
import android.os.Bundle
import android.os.Environment
import android.os.Parcelable
import android.preference.PreferenceManager
import android.view.*
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.lifecycle.ViewModelProviders
import androidx.localbroadcastmanager.content.LocalBroadcastManager
@ -21,8 +29,15 @@ import com.xwray.groupie.Section
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import icepick.State
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.dialog_title.view.*
import kotlinx.android.synthetic.main.fragment_subscription.*
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import kotlin.math.floor
import kotlin.math.max
import kotlinx.android.synthetic.main.dialog_title.view.itemAdditionalDetails
import kotlinx.android.synthetic.main.dialog_title.view.itemTitleView
import kotlinx.android.synthetic.main.fragment_subscription.items_list
import org.schabi.newpipe.R
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
@ -30,21 +45,29 @@ import org.schabi.newpipe.fragments.BaseStateFragment
import org.schabi.newpipe.local.subscription.SubscriptionViewModel.SubscriptionState
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog
import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialog
import org.schabi.newpipe.local.subscription.item.*
import org.schabi.newpipe.local.subscription.item.ChannelItem
import org.schabi.newpipe.local.subscription.item.EmptyPlaceholderItem
import org.schabi.newpipe.local.subscription.item.FeedGroupAddItem
import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem
import org.schabi.newpipe.local.subscription.item.FeedGroupCarouselItem
import org.schabi.newpipe.local.subscription.item.FeedImportExportItem
import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem
import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem.Companion.PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService.EXPORT_COMPLETE_ACTION
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService.KEY_FILE_PATH
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.*
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.IMPORT_COMPLETE_ACTION
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE
import org.schabi.newpipe.report.UserAction
import org.schabi.newpipe.util.*
import org.schabi.newpipe.util.AnimationUtils.animateView
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.floor
import kotlin.math.max
import org.schabi.newpipe.util.FilePickerActivityHelper
import org.schabi.newpipe.util.NavigationHelper
import org.schabi.newpipe.util.OnClickGesture
import org.schabi.newpipe.util.ShareUtils
import org.schabi.newpipe.util.ThemeHelper
class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
private lateinit var viewModel: SubscriptionViewModel
@ -74,9 +97,9 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
setHasOptionsMenu(true)
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Fragment LifeCycle
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -120,9 +143,9 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
disposables.dispose()
}
//////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////
// Menu
//////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
@ -150,7 +173,6 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
importExportItem.isExpanded = false
importExportItem.notifyChanged(FeedImportExportItem.REFRESH_EXPANDED_STATUS)
}
}
}
@ -198,9 +220,9 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
}
}
//////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////
// Fragment Views
//////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////
private fun setupInitialLayout() {
Section().apply {
@ -243,7 +265,6 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
{ onExportSelected() },
importExportItemExpandedState ?: false)
groupAdapter.add(Section(importExportItem, listOf(subscriptionsSection)))
}
override fun initViews(rootView: View, savedInstanceState: Bundle?) {
@ -366,9 +387,9 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
items_list.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) }
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Contract
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
override fun showLoading() {
super.showLoading()
@ -380,9 +401,9 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
animateView(items_list, true, 200)
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Fragment Error Handling
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
override fun onError(exception: Throwable): Boolean {
if (super.onError(exception)) return true
@ -391,9 +412,9 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
return true
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Grid Mode
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// TODO: Move these out of this class, as it can be reused
@ -405,8 +426,8 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
getString(R.string.list_view_mode_auto_key) -> {
val configuration = resources.configuration
(configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
&& configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE))
(configuration.orientation == Configuration.ORIENTATION_LANDSCAPE &&
configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE))
}
getString(R.string.list_view_mode_grid_key) -> true
else -> false

View File

@ -6,11 +6,11 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.xwray.groupie.Group
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.TimeUnit
import org.schabi.newpipe.local.feed.FeedDatabaseManager
import org.schabi.newpipe.local.subscription.item.ChannelItem
import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem
import org.schabi.newpipe.util.DEFAULT_THROTTLE_TIMEOUT
import java.util.concurrent.TimeUnit
class SubscriptionViewModel(application: Application) : AndroidViewModel(application) {
private var feedDatabaseManager: FeedDatabaseManager = FeedDatabaseManager(application)

View File

@ -32,4 +32,4 @@ class FeedGroupCarouselDecoration(context: Context) : RecyclerView.ItemDecoratio
outRect.right = marginStartEnd
}
}
}
}

View File

@ -22,19 +22,36 @@ import com.xwray.groupie.Section
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import icepick.Icepick
import icepick.State
import kotlinx.android.synthetic.main.dialog_feed_group_create.*
import java.io.Serializable
import kotlinx.android.synthetic.main.dialog_feed_group_create.cancel_button
import kotlinx.android.synthetic.main.dialog_feed_group_create.confirm_button
import kotlinx.android.synthetic.main.dialog_feed_group_create.delete_button
import kotlinx.android.synthetic.main.dialog_feed_group_create.delete_screen_message
import kotlinx.android.synthetic.main.dialog_feed_group_create.group_name_input
import kotlinx.android.synthetic.main.dialog_feed_group_create.group_name_input_container
import kotlinx.android.synthetic.main.dialog_feed_group_create.icon_preview
import kotlinx.android.synthetic.main.dialog_feed_group_create.icon_selector
import kotlinx.android.synthetic.main.dialog_feed_group_create.options_root
import kotlinx.android.synthetic.main.dialog_feed_group_create.select_channel_button
import kotlinx.android.synthetic.main.dialog_feed_group_create.selected_subscription_count_view
import kotlinx.android.synthetic.main.dialog_feed_group_create.separator
import kotlinx.android.synthetic.main.dialog_feed_group_create.subscriptions_selector
import kotlinx.android.synthetic.main.dialog_feed_group_create.subscriptions_selector_header_info
import kotlinx.android.synthetic.main.dialog_feed_group_create.subscriptions_selector_list
import org.schabi.newpipe.R
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
import org.schabi.newpipe.database.subscription.SubscriptionEntity
import org.schabi.newpipe.local.subscription.FeedGroupIcon
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog.ScreenState.*
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog.ScreenState.DeleteScreen
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog.ScreenState.IconPickerScreen
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog.ScreenState.InitialScreen
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog.ScreenState.SubscriptionsPickerScreen
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialogViewModel.DialogEvent.ProcessingEvent
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialogViewModel.DialogEvent.SuccessEvent
import org.schabi.newpipe.local.subscription.item.EmptyPlaceholderItem
import org.schabi.newpipe.local.subscription.item.PickerIconItem
import org.schabi.newpipe.local.subscription.item.PickerSubscriptionItem
import org.schabi.newpipe.util.ThemeHelper
import java.io.Serializable
class FeedGroupDialog : DialogFragment() {
private lateinit var viewModel: FeedGroupDialogViewModel
@ -120,9 +137,9 @@ class FeedGroupDialog : DialogFragment() {
showScreen(currentScreen)
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Setup
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
private fun setupListeners() {
delete_button.setOnClickListener { showScreen(DeleteScreen) }
@ -294,9 +311,9 @@ class FeedGroupDialog : DialogFragment() {
}
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Screen Selector
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
private fun showScreen(screen: ScreenState) {
currentScreen = screen
@ -330,9 +347,9 @@ class FeedGroupDialog : DialogFragment() {
}
}
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Utils
///////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
private fun hideKeyboard() {
val inputMethodManager = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
@ -363,4 +380,4 @@ class FeedGroupDialog : DialogFragment() {
return dialog
}
}
}
}

View File

@ -16,7 +16,6 @@ import org.schabi.newpipe.local.feed.FeedDatabaseManager
import org.schabi.newpipe.local.subscription.FeedGroupIcon
import org.schabi.newpipe.local.subscription.SubscriptionManager
class FeedGroupDialogViewModel(applicationContext: Context, val groupId: Long = FeedGroupEntity.GROUP_ALL_ID) : ViewModel() {
class Factory(val context: Context, val groupId: Long = FeedGroupEntity.GROUP_ALL_ID) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -84,4 +83,4 @@ class FeedGroupDialogViewModel(applicationContext: Context, val groupId: Long =
object ProcessingEvent : DialogEvent()
object SuccessEvent : DialogEvent()
}
}
}

View File

@ -16,15 +16,15 @@ import com.xwray.groupie.TouchCallback
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import icepick.Icepick
import icepick.State
import kotlinx.android.synthetic.main.dialog_feed_group_reorder.*
import java.util.Collections
import kotlinx.android.synthetic.main.dialog_feed_group_reorder.confirm_button
import kotlinx.android.synthetic.main.dialog_feed_group_reorder.feed_groups_list
import org.schabi.newpipe.R
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialogViewModel.DialogEvent.ProcessingEvent
import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialogViewModel.DialogEvent.SuccessEvent
import org.schabi.newpipe.local.subscription.item.FeedGroupReorderItem
import org.schabi.newpipe.util.ThemeHelper
import java.util.*
import kotlin.collections.ArrayList
class FeedGroupReorderDialog : DialogFragment() {
private lateinit var viewModel: FeedGroupReorderDialogViewModel
@ -93,8 +93,11 @@ class FeedGroupReorderDialog : DialogFragment() {
private fun getItemTouchCallback(): SimpleCallback {
return object : TouchCallback() {
override fun onMove(recyclerView: RecyclerView, source: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder): Boolean {
override fun onMove(
recyclerView: RecyclerView,
source: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val sourceIndex = source.adapterPosition
val targetIndex = target.adapterPosition
@ -109,4 +112,4 @@ class FeedGroupReorderDialog : DialogFragment() {
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {}
}
}
}
}

View File

@ -49,4 +49,4 @@ class FeedGroupReorderDialogViewModel(application: Application) : AndroidViewMod
object ProcessingEvent : DialogEvent()
object SuccessEvent : DialogEvent()
}
}
}

View File

@ -4,19 +4,21 @@ import android.content.Context
import com.nostra13.universalimageloader.core.ImageLoader
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import com.xwray.groupie.kotlinandroidextensions.Item
import kotlinx.android.synthetic.main.list_channel_item.*
import kotlinx.android.synthetic.main.list_channel_item.itemAdditionalDetails
import kotlinx.android.synthetic.main.list_channel_item.itemChannelDescriptionView
import kotlinx.android.synthetic.main.list_channel_item.itemThumbnailView
import kotlinx.android.synthetic.main.list_channel_item.itemTitleView
import org.schabi.newpipe.R
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
import org.schabi.newpipe.util.ImageDisplayConstants
import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.OnClickGesture
class ChannelItem(
private val infoItem: ChannelInfoItem,
private val subscriptionId: Long = -1L,
var itemVersion: ItemVersion = ItemVersion.NORMAL,
var gesturesListener: OnClickGesture<ChannelInfoItem>? = null
private val infoItem: ChannelInfoItem,
private val subscriptionId: Long = -1L,
var itemVersion: ItemVersion = ItemVersion.NORMAL,
var gesturesListener: OnClickGesture<ChannelInfoItem>? = null
) : Item() {
override fun getId(): Long = if (subscriptionId == -1L) super.getId() else subscriptionId
@ -62,4 +64,4 @@ class ChannelItem(
override fun getSpanSize(spanCount: Int, position: Int): Int {
return if (itemVersion == ItemVersion.GRID) 1 else spanCount
}
}
}

View File

@ -7,4 +7,4 @@ import org.schabi.newpipe.R
class EmptyPlaceholderItem : Item() {
override fun getLayout(): Int = R.layout.list_empty_view
override fun bind(viewHolder: GroupieViewHolder, position: Int) {}
}
}

View File

@ -7,4 +7,4 @@ import org.schabi.newpipe.R
class FeedGroupAddItem : Item() {
override fun getLayout(): Int = R.layout.feed_group_add_new_item
override fun bind(viewHolder: GroupieViewHolder, position: Int) {}
}
}

View File

@ -2,15 +2,16 @@ package org.schabi.newpipe.local.subscription.item
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import com.xwray.groupie.kotlinandroidextensions.Item
import kotlinx.android.synthetic.main.feed_group_card_item.*
import kotlinx.android.synthetic.main.feed_group_card_item.icon
import kotlinx.android.synthetic.main.feed_group_card_item.title
import org.schabi.newpipe.R
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
import org.schabi.newpipe.local.subscription.FeedGroupIcon
data class FeedGroupCardItem(
val groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
val name: String,
val icon: FeedGroupIcon
val groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
val name: String,
val icon: FeedGroupIcon
) : Item() {
constructor (feedGroupEntity: FeedGroupEntity) : this(feedGroupEntity.uid, feedGroupEntity.name, feedGroupEntity.icon)
@ -27,4 +28,4 @@ data class FeedGroupCardItem(
viewHolder.title.text = name
viewHolder.icon.setImageResource(icon.getDrawableRes(viewHolder.containerView.context))
}
}
}

View File

@ -8,7 +8,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.xwray.groupie.GroupAdapter
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import com.xwray.groupie.kotlinandroidextensions.Item
import kotlinx.android.synthetic.main.feed_item_carousel.*
import kotlinx.android.synthetic.main.feed_item_carousel.recycler_view
import org.schabi.newpipe.R
import org.schabi.newpipe.local.subscription.decoration.FeedGroupCarouselDecoration
@ -54,4 +54,4 @@ class FeedGroupCarouselItem(context: Context, private val carouselAdapter: Group
listState = linearLayoutManager?.onSaveInstanceState()
}
}
}

View File

@ -6,19 +6,21 @@ import androidx.recyclerview.widget.ItemTouchHelper.DOWN
import androidx.recyclerview.widget.ItemTouchHelper.UP
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import com.xwray.groupie.kotlinandroidextensions.Item
import kotlinx.android.synthetic.main.feed_group_reorder_item.*
import kotlinx.android.synthetic.main.feed_group_reorder_item.group_icon
import kotlinx.android.synthetic.main.feed_group_reorder_item.group_name
import kotlinx.android.synthetic.main.feed_group_reorder_item.handle
import org.schabi.newpipe.R
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
import org.schabi.newpipe.local.subscription.FeedGroupIcon
data class FeedGroupReorderItem(
val groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
val name: String,
val icon: FeedGroupIcon,
val dragCallback: ItemTouchHelper
val groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
val name: String,
val icon: FeedGroupIcon,
val dragCallback: ItemTouchHelper
) : Item() {
constructor (feedGroupEntity: FeedGroupEntity, dragCallback: ItemTouchHelper)
: this(feedGroupEntity.uid, feedGroupEntity.name, feedGroupEntity.icon, dragCallback)
constructor (feedGroupEntity: FeedGroupEntity, dragCallback: ItemTouchHelper) :
this(feedGroupEntity.uid, feedGroupEntity.name, feedGroupEntity.icon, dragCallback)
override fun getId(): Long {
return when (groupId) {
@ -45,4 +47,4 @@ data class FeedGroupReorderItem(
override fun getDragDirs(): Int {
return UP or DOWN
}
}
}

View File

@ -9,7 +9,11 @@ import android.widget.TextView
import androidx.annotation.DrawableRes
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import com.xwray.groupie.kotlinandroidextensions.Item
import kotlinx.android.synthetic.main.feed_import_export_group.*
import kotlinx.android.synthetic.main.feed_import_export_group.export_to_options
import kotlinx.android.synthetic.main.feed_import_export_group.import_export
import kotlinx.android.synthetic.main.feed_import_export_group.import_export_expand_icon
import kotlinx.android.synthetic.main.feed_import_export_group.import_export_options
import kotlinx.android.synthetic.main.feed_import_export_group.import_from_options
import org.schabi.newpipe.R
import org.schabi.newpipe.extractor.NewPipe
import org.schabi.newpipe.extractor.exceptions.ExtractionException
@ -19,10 +23,10 @@ import org.schabi.newpipe.util.ThemeHelper
import org.schabi.newpipe.views.CollapsibleView
class FeedImportExportItem(
val onImportPreviousSelected: () -> Unit,
val onImportFromServiceSelected: (Int) -> Unit,
val onExportSelected: () -> Unit,
var isExpanded: Boolean = false
val onImportPreviousSelected: () -> Unit,
val onImportFromServiceSelected: (Int) -> Unit,
val onExportSelected: () -> Unit,
var isExpanded: Boolean = false
) : Item() {
companion object {
const val REFRESH_EXPANDED_STATUS = 123
@ -104,7 +108,6 @@ class FeedImportExportItem(
} catch (e: ExtractionException) {
throw RuntimeException("Services array contains an entry that it's not a valid service name ($serviceName)", e)
}
}
}
@ -113,4 +116,4 @@ class FeedImportExportItem(
ThemeHelper.resolveResourceIdFromAttr(listHolder.context, R.attr.ic_save), listHolder)
previousBackupItem.setOnClickListener { onExportSelected() }
}
}
}

View File

@ -3,7 +3,7 @@ package org.schabi.newpipe.local.subscription.item
import android.view.View.OnClickListener
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import com.xwray.groupie.kotlinandroidextensions.Item
import kotlinx.android.synthetic.main.header_item.*
import kotlinx.android.synthetic.main.header_item.header_title
import org.schabi.newpipe.R
class HeaderItem(val title: String, private val onClickListener: (() -> Unit)? = null) : Item() {
@ -16,4 +16,4 @@ class HeaderItem(val title: String, private val onClickListener: (() -> Unit)? =
val listener: OnClickListener? = if (onClickListener != null) OnClickListener { onClickListener.invoke() } else null
viewHolder.root.setOnClickListener(listener)
}
}
}

View File

@ -1,18 +1,21 @@
package org.schabi.newpipe.local.subscription.item
import android.view.View.*
import android.view.View.GONE
import android.view.View.OnClickListener
import android.view.View.VISIBLE
import androidx.annotation.DrawableRes
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import com.xwray.groupie.kotlinandroidextensions.Item
import kotlinx.android.synthetic.main.header_with_menu_item.*
import kotlinx.android.synthetic.main.header_with_menu_item.header_menu_item
import kotlinx.android.synthetic.main.header_with_menu_item.header_title
import org.schabi.newpipe.R
class HeaderWithMenuItem(
val title: String,
@DrawableRes val itemIcon: Int = 0,
var showMenuItem: Boolean = true,
private val onClickListener: (() -> Unit)? = null,
private val menuItemOnClickListener: (() -> Unit)? = null
val title: String,
@DrawableRes val itemIcon: Int = 0,
var showMenuItem: Boolean = true,
private val onClickListener: (() -> Unit)? = null,
private val menuItemOnClickListener: (() -> Unit)? = null
) : Item() {
companion object {
const val PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM = 1
@ -46,4 +49,4 @@ class HeaderWithMenuItem(
private fun updateMenuItemVisibility(viewHolder: GroupieViewHolder) {
viewHolder.header_menu_item.visibility = if (showMenuItem) VISIBLE else GONE
}
}
}

View File

@ -4,7 +4,7 @@ import android.content.Context
import androidx.annotation.DrawableRes
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import com.xwray.groupie.kotlinandroidextensions.Item
import kotlinx.android.synthetic.main.picker_icon_item.*
import kotlinx.android.synthetic.main.picker_icon_item.icon_view
import org.schabi.newpipe.R
import org.schabi.newpipe.local.subscription.FeedGroupIcon
@ -17,4 +17,4 @@ class PickerIconItem(context: Context, val icon: FeedGroupIcon) : Item() {
override fun bind(viewHolder: GroupieViewHolder, position: Int) {
viewHolder.icon_view.setImageResource(iconRes)
}
}
}

View File

@ -5,7 +5,9 @@ import com.nostra13.universalimageloader.core.DisplayImageOptions
import com.nostra13.universalimageloader.core.ImageLoader
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
import com.xwray.groupie.kotlinandroidextensions.Item
import kotlinx.android.synthetic.main.picker_subscription_item.*
import kotlinx.android.synthetic.main.picker_subscription_item.selected_highlight
import kotlinx.android.synthetic.main.picker_subscription_item.thumbnail_view
import kotlinx.android.synthetic.main.picker_subscription_item.title_view
import org.schabi.newpipe.R
import org.schabi.newpipe.database.subscription.SubscriptionEntity
import org.schabi.newpipe.util.AnimationUtils
@ -48,4 +50,4 @@ data class PickerSubscriptionItem(val subscriptionEntity: SubscriptionEntity, va
override fun getId(): Long {
return subscriptionEntity.uid
}
}
}

View File

@ -80,8 +80,8 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItemHolder;
import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback;
import org.schabi.newpipe.player.resolver.MediaSourceTag;
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.AndroidTvUtils;
import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.KoreUtil;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper;

View File

@ -43,4 +43,4 @@ class DurationListPreference : ListPreference {
entries = newEntryTitles
}
}
}

View File

@ -5,8 +5,8 @@ import org.schabi.newpipe.streams.Mp4DashReader.Mdia;
import org.schabi.newpipe.streams.Mp4DashReader.Mp4DashChunk;
import org.schabi.newpipe.streams.Mp4DashReader.Mp4DashSample;
import org.schabi.newpipe.streams.Mp4DashReader.Mp4Track;
import org.schabi.newpipe.streams.Mp4DashReader.TrunEntry;
import org.schabi.newpipe.streams.Mp4DashReader.TrackKind;
import org.schabi.newpipe.streams.Mp4DashReader.TrunEntry;
import org.schabi.newpipe.streams.io.SharpStream;
import java.io.IOException;

View File

@ -79,4 +79,4 @@ class ExceptionUtils {
return false
}
}
}
}

View File

@ -24,4 +24,4 @@ class UrlFinder {
return null
}
}
}
}

View File

@ -25,6 +25,7 @@ import android.view.ViewTreeObserver;
import android.widget.SeekBar;
import androidx.appcompat.widget.AppCompatSeekBar;
import org.schabi.newpipe.util.AndroidTvUtils;
/**

View File

@ -6,8 +6,8 @@ import android.system.ErrnoException;
import android.system.OsConstants;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.schabi.newpipe.DownloaderImpl;

View File

@ -6,9 +6,10 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import androidx.annotation.NonNull;
import android.util.Log;
import androidx.annotation.NonNull;
import java.io.File;
import java.util.ArrayList;

View File

@ -3,9 +3,10 @@ package us.shandian.giga.io;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import androidx.annotation.NonNull;
import android.util.Log;
import androidx.annotation.NonNull;
import org.schabi.newpipe.streams.io.SharpStream;
import java.io.FileInputStream;

View File

@ -8,6 +8,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.DocumentsContract;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;

View File

@ -7,10 +7,11 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.DocumentsContract;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.documentfile.provider.DocumentFile;
import androidx.fragment.app.Fragment;
import org.schabi.newpipe.streams.io.SharpStream;

View File

@ -1,6 +1,7 @@
package us.shandian.giga.ui.common;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

View File

@ -17,7 +17,6 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.Toast;
import androidx.annotation.NonNull;

View File

@ -1,10 +1,9 @@
<?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"
xmlns:tools="http://schemas.android.com/tools">
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_item_remove_watched"
android:title="@string/remove_watched"
app:showAsAction="never"/>
</menu>
</menu>

View File

@ -27,4 +27,4 @@ class FeedGroupIconTest {
assertTrue("Repeated icon (current item: ${groupIcon.name} - ${groupIcon.id})", added)
}
}
}
}

View File

@ -1,14 +1,14 @@
package org.schabi.newpipe.util
import java.io.IOException
import java.io.InterruptedIOException
import java.net.SocketException
import javax.net.ssl.SSLException
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.schabi.newpipe.util.ExceptionUtils.Companion.hasAssignableCause
import org.schabi.newpipe.util.ExceptionUtils.Companion.hasExactCause
import java.io.IOException
import java.io.InterruptedIOException
import java.net.SocketException
import javax.net.ssl.SSLException
class ExceptionUtilsTest {
@Test fun `assignable causes`() {
@ -66,4 +66,4 @@ class ExceptionUtilsTest {
assertFalse(hasExactCause(Exception(IllegalStateException(Exception(SocketException()))), IOException::class.java))
assertFalse(hasExactCause(Exception(IllegalStateException(Exception(InterruptedIOException()))), IOException::class.java))
}
}
}

View File

@ -96,4 +96,4 @@ class UrlFinderTest {
assertEquals("https://www.youtube.com/watch?v=dQw4w9WgXcQ",
UrlFinder.firstUrlFromInput("https://www.youtube.com/watch?v=dQw4w9WgXcQ\"Not PartOfTheUrl"))
}
}
}