Skip to content

Commit

Permalink
Implement new feed and subscriptions groups
Browse files Browse the repository at this point in the history
- Introduce Groupie for easier lists implementations
- Show the proper view count string ('watching' for live streams)
- Introduce PrettyTime for time formatting
- Use some of the new components of the Android Architecture
- Add a bunch of icons for groups, using vectors, which still is
compatible with older APIs through the compatibility layer
  • Loading branch information
mauriciocolli committed Apr 27, 2019
1 parent 056fed3 commit 2c88500
Show file tree
Hide file tree
Showing 195 changed files with 4,211 additions and 1,432 deletions.
12 changes: 12 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

androidExtensions {
experimental = true
}
}

ext {
Expand Down Expand Up @@ -80,6 +84,13 @@ dependencies {
implementation "androidx.cardview:cardview:1.0.0"
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

implementation 'com.xwray:groupie:2.3.0'
implementation 'com.xwray:groupie-kotlin-android-extensions:2.3.0'

implementation 'androidx.lifecycle:lifecycle-livedata:2.0.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'

implementation 'ch.acra:acra:4.9.2' //4.11

implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
Expand All @@ -97,6 +108,7 @@ dependencies {
implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
implementation 'org.ocpsoft.prettytime:prettytime:4.0.1.Final'

implementation "androidx.room:room-runtime:${roomDbLibVersion}"
implementation "androidx.room:room-rxjava2:${roomDbLibVersion}"
Expand Down
1 change: 1 addition & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

-dontobfuscate
-keep class org.schabi.newpipe.extractor.timeago.patterns.** { *; }
-keep class org.ocpsoft.prettytime.i18n.** { *; }

-keep class org.mozilla.javascript.** { *; }

Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@

<service android:name=".local.subscription.services.SubscriptionsImportService"/>
<service android:name=".local.subscription.services.SubscriptionsExportService"/>
<service android:name=".local.feed.service.FeedLoadService"/>

<activity
android:name=".PanicResponderActivity"
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/org/schabi/newpipe/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ private void tabSelected(MenuItem item) throws ExtractionException {
NavigationHelper.openSubscriptionFragment(getSupportFragmentManager());
break;
case ITEM_ID_FEED:
NavigationHelper.openWhatsNewFragment(getSupportFragmentManager());
NavigationHelper.openFeedFragment(getSupportFragmentManager());
break;
case ITEM_ID_BOOKMARKS:
NavigationHelper.openBookmarksFragment(getSupportFragmentManager());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ public class AboutActivity extends AppCompatActivity {
new SoftwareComponent("ExoPlayer", "2014-2017", "Google Inc", "https://github.com/google/ExoPlayer", StandardLicenses.APACHE2),
new SoftwareComponent("RxAndroid", "2015", "The RxAndroid authors", "https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2),
new SoftwareComponent("RxJava", "2016-present", "RxJava Contributors", "https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2),
new SoftwareComponent("RxBinding", "2015", "Jake Wharton", "https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2)
new SoftwareComponent("RxBinding", "2015", "Jake Wharton", "https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2),
new SoftwareComponent("PrettyTime", "2012", "Lincoln Baxter, III", "https://github.com/ocpsoft/prettytime", StandardLicenses.APACHE2),
};

/**
Expand Down
19 changes: 17 additions & 2 deletions app/src/main/java/org/schabi/newpipe/database/Converters.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package org.schabi.newpipe.database;

import android.arch.persistence.room.TypeConverter;

import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.local.subscription.FeedGroupIcon;

import java.util.Date;

import androidx.room.TypeConverter;

public class Converters {

/**
Expand Down Expand Up @@ -37,4 +38,18 @@ public static StreamType streamTypeOf(String value) {
public static String stringOf(StreamType streamType) {
return streamType.name();
}

@TypeConverter
public static Integer integerOf(FeedGroupIcon feedGroupIcon) {
return feedGroupIcon.getId();
}

@TypeConverter
public static FeedGroupIcon feedGroupIconOf(Integer id) {
for (FeedGroupIcon icon : FeedGroupIcon.values()) {
if (icon.getId() == id) return icon;
}

throw new IllegalArgumentException("There's no feed group icon with the id \"" + id + "\"");
}
}
24 changes: 22 additions & 2 deletions app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.room.Query
import io.reactivex.Flowable
import org.schabi.newpipe.database.feed.model.FeedEntity
import org.schabi.newpipe.database.stream.model.StreamEntity
import java.util.*

@Dao
abstract class FeedDAO {
Expand All @@ -20,6 +21,8 @@ abstract class FeedDAO {
ON s.uid = f.stream_id
ORDER BY s.upload_date IS NULL DESC, s.upload_date DESC
LIMIT 500
""")
abstract fun getAllStreams(): Flowable<List<StreamEntity>>

Expand All @@ -36,12 +39,29 @@ abstract class FeedDAO {
ON fg.uid = fgs.group_id
WHERE fgs.group_id = :groupId
ORDER BY s.upload_date IS NULL DESC, s.upload_date DESC
LIMIT 500
""")
abstract fun getAllStreamsFromGroup(groupId: Long): Flowable<List<StreamEntity>>

@Insert(onConflict = OnConflictStrategy.FAIL)
@Query("""
DELETE FROM feed WHERE
feed.stream_id IN (
SELECT s.uid FROM streams s
INNER JOIN feed f
ON s.uid = f.stream_id
WHERE s.upload_date < :date
)
""")
abstract fun unlinkStreamsOlderThan(date: Date)

@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract fun insert(feedEntity: FeedEntity)

@Insert(onConflict = OnConflictStrategy.FAIL)
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract fun insertAll(entities: List<FeedEntity>): List<Long>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,43 @@ package org.schabi.newpipe.database.feed.dao

import androidx.room.*
import io.reactivex.Flowable
import io.reactivex.Maybe
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
import org.schabi.newpipe.database.feed.model.FeedGroupSubscriptionEntity

@Dao
abstract class FeedGroupDAO {
@Query("DELETE FROM feed_group")
abstract fun deleteAll(): Int

@Query("SELECT * FROM feed_group")
abstract fun getAll(): Flowable<List<FeedGroupEntity>>

@Query("SELECT * FROM feed_group WHERE uid = :groupId")
abstract fun getGroup(groupId: Long): Maybe<FeedGroupEntity>

@Insert(onConflict = OnConflictStrategy.FAIL)
abstract fun insert(feedEntity: FeedGroupEntity)
abstract fun insert(feedEntity: FeedGroupEntity): Long

@Update(onConflict = OnConflictStrategy.IGNORE)
abstract fun update(feedGroupEntity: FeedGroupEntity): Int

@Query("DELETE FROM feed_group")
abstract fun deleteAll(): Int

@Query("DELETE FROM feed_group WHERE uid = :groupId")
abstract fun delete(groupId: Long): Int

@Query("SELECT subscription_id FROM feed_group_subscription_join WHERE group_id = :groupId")
abstract fun getSubscriptionIdsFor(groupId: Long): Flowable<List<Long>>

@Query("DELETE FROM feed_group_subscription_join WHERE group_id = :groupId")
abstract fun deleteSubscriptionsFromGroup(groupId: Long): Int

@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract fun insertSubscriptionsToGroup(entities: List<FeedGroupSubscriptionEntity>): List<Long>

@Transaction
open fun updateSubscriptionsForGroup(groupId: Long, subscriptionIds: List<Long>) {
deleteSubscriptionsFromGroup(groupId)
insertSubscriptionsToGroup(subscriptionIds.map { FeedGroupSubscriptionEntity(groupId, it) })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import org.schabi.newpipe.database.feed.model.FeedGroupEntity.Companion.FEED_GROUP_TABLE
import org.schabi.newpipe.local.subscription.FeedGroupIcon

@Entity(tableName = FEED_GROUP_TABLE)
data class FeedGroupEntity(
Expand All @@ -15,7 +16,7 @@ data class FeedGroupEntity(
var name: String,

@ColumnInfo(name = ICON)
var iconId: Int
var icon: FeedGroupIcon
) {
companion object {
const val FEED_GROUP_TABLE = "feed_group"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.schabi.newpipe.database.subscription

import androidx.room.*
import io.reactivex.Flowable
import io.reactivex.Maybe
import org.schabi.newpipe.database.BasicDAO

@Dao
abstract class SubscriptionDAO : BasicDAO<SubscriptionEntity> {
@Query("SELECT COUNT(*) FROM subscriptions")
abstract fun rowCount(): Flowable<Long>

@Query("SELECT * FROM subscriptions WHERE service_id = :serviceId")
abstract override fun listByService(serviceId: Int): Flowable<List<SubscriptionEntity>>

@Query("SELECT * FROM subscriptions ORDER BY name COLLATE NOCASE ASC")
abstract override fun getAll(): Flowable<List<SubscriptionEntity>>

@Query("SELECT * FROM subscriptions WHERE url LIKE :url AND service_id = :serviceId")
abstract fun getSubscriptionFlowable(serviceId: Int, url: String): Flowable<List<SubscriptionEntity>>

@Query("SELECT * FROM subscriptions WHERE url LIKE :url AND service_id = :serviceId")
abstract fun getSubscription(serviceId: Int, url: String): Maybe<SubscriptionEntity>

@Query("DELETE FROM subscriptions")
abstract override fun deleteAll(): Int

@Query("DELETE FROM subscriptions WHERE url LIKE :url AND service_id = :serviceId")
abstract fun deleteSubscription(serviceId: Int, url: String): Int

@Query("SELECT uid FROM subscriptions WHERE url LIKE :url AND service_id = :serviceId")
internal abstract fun getSubscriptionIdInternal(serviceId: Int, url: String): Long?

@Insert(onConflict = OnConflictStrategy.IGNORE)
internal abstract fun silentInsertAllInternal(entities: List<SubscriptionEntity>): List<Long>

@Transaction
open fun upsertAll(entities: List<SubscriptionEntity>): List<SubscriptionEntity> {
val insertUidList = silentInsertAllInternal(entities)

val entityIds = ArrayList<Long>(entities.size)
for ((index, uid) in insertUidList.withIndex()) {
val newerEntity = entities[index]
if (uid != -1L) {
entityIds.add(uid)
newerEntity.uid = uid
continue
}

entityIds.add(newerEntity.uid)
}

update(entities)
return entities
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package org.schabi.newpipe.database.subscription;

import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.Ignore;
import android.arch.persistence.room.Index;
import android.arch.persistence.room.PrimaryKey;
import android.support.annotation.NonNull;

import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.util.Constants;

import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.Index;
import androidx.room.PrimaryKey;

import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_SERVICE_ID;
import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_TABLE;
import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_URL;
Expand All @@ -19,14 +19,14 @@
indices = {@Index(value = {SUBSCRIPTION_SERVICE_ID, SUBSCRIPTION_URL}, unique = true)})
public class SubscriptionEntity {

public final static String SUBSCRIPTION_UID = "uid";
final static String SUBSCRIPTION_TABLE = "subscriptions";
final static String SUBSCRIPTION_SERVICE_ID = "service_id";
final static String SUBSCRIPTION_URL = "url";
final static String SUBSCRIPTION_NAME = "name";
final static String SUBSCRIPTION_AVATAR_URL = "avatar_url";
final static String SUBSCRIPTION_SUBSCRIBER_COUNT = "subscriber_count";
final static String SUBSCRIPTION_DESCRIPTION = "description";
public static final String SUBSCRIPTION_UID = "uid";
public static final String SUBSCRIPTION_TABLE = "subscriptions";
public static final String SUBSCRIPTION_SERVICE_ID = "service_id";
public static final String SUBSCRIPTION_URL = "url";
public static final String SUBSCRIPTION_NAME = "name";
public static final String SUBSCRIPTION_AVATAR_URL = "avatar_url";
public static final String SUBSCRIPTION_SUBSCRIBER_COUNT = "subscriber_count";
public static final String SUBSCRIPTION_DESCRIPTION = "description";

@PrimaryKey(autoGenerate = true)
private long uid = 0;
Expand Down
Loading

0 comments on commit 2c88500

Please sign in to comment.