Merge branch 'develop' into feature/importFahrplan

This commit is contained in:
Felix 2020-04-04 17:28:00 +02:00
commit 38998661ae
139 changed files with 653 additions and 302 deletions

View file

@ -1,9 +1,16 @@
version: 2
jobs:
build:
working_directory: ~/code
version: 2.1
references:
workspace_root: &workspace_root
~/code
container_config: &container_config
docker:
- image: circleci/android:api-28
working_directory: *workspace_root
environment:
JVM_OPTS: -XX\:MaxHeapSize\=2048m -Xmx1536m
LIBS: NoFree
@ -11,88 +18,182 @@ jobs:
APPCENTER_OWNER: nicidienase
APPCENTER_GROUP: "Collaborators"
RELEASENOTES_FILE: "release_notes.txt"
branches:
only:
- master
- develop
- /feature\/.*/
steps:
- checkout
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "touch/build.gradle" }}-{{ checksum "leanback/build.gradle" }}-{{ checksum "common/build.gradle" }}
- run:
name: Setup env
attach_workspace: &attach_workspace
attach_workspace:
at: *workspace_root
setup_env: &setup_env
name: Setup environment
command: |
.circleci/setup_env.sh >> $BASH_ENV
echo "VERSION_CODE_TOUCH=$(.circleci/getVersionCode.sh -t)" >> $BASH_ENV
echo "VERSION_CODE_LEANBACK=$(.circleci/getVersionCode.sh -l)" >> $BASH_ENV
# . $BASH_ENV
# echo "STAGE=${STAGE}"
# echo "VERSION_NAME=${VERSION_NAME}"
# echo "VersionCode: $(.circleci/getVersionCode.sh -t)"
# echo "BUILD_TYPE_LOWER=${BUILD_TYPE_LOWER}"
# echo "STAGE_LOWER=${STAGE_LOWER}"
# echo "LIBS_LOWER=${LIBS_LOWER}"
general_cache_key: &general_cache_key
key: app-{{ checksum ".circleci/config.yml" }}-{{ checksum "gradle.properties" }}-{{ checksum "build.gradle" }}-{{ checksum "touch/build.gradle" }}-{{ checksum "leanback/build.gradle" }}-{{ checksum "common/build.gradle" }}-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}
jobs:
build:
<<: *container_config
steps:
- checkout
- restore_cache:
<<: *general_cache_key
- run:
<<: *setup_env
- run:
name: Download Dependencies
command: ./gradlew $SIGN_CONFIG androidDependencies
- run:
name: ktlint
command: |
./gradlew $SIGN_CONFIG --continue \
common:ktlint${STAGE}${LIBS}${BUILD_TYPE}Check \
touch:ktlint${STAGE}${LIBS}${BUILD_TYPE}Check \
leanback:ktlint${STAGE}${LIBS}${BUILD_TYPE}Check
./gradlew $KEY_CONFIG $SIGN_CONFIG \
-PversionCode=$VERSION_CODE_TOUCH \
-PversionName=${VERSION_NAME} \
androidDependencies
- run:
name: Build Touch
command: |
./gradlew $SIGN_CONFIG \
./gradlew $SIGN_CONFIG $KEY_CONFIG \
-PversionCode=$VERSION_CODE_TOUCH \
-PversionName=${VERSION_NAME} \
touch:assemble${STAGE_LOWER}${LIBS}${BUILD_TYPE}
- run:
name: Build Leanback
command: |
./gradlew $SIGN_CONFIG \
-PversionCode=$VERSION_CODE_LEANBACK \
-PversionName=${VERSION_NAME} \
leanback:assemble${STAGE_LOWER}${LIBS}${BUILD_TYPE}
- run:
name: Test
command: |
./gradlew $SIGN_CONFIG --continue \
common:test${STAGE}${LIBS}${BUILD_TYPE}UnitTest \
common:lint${STAGE}${LIBS}${BUILD_TYPE} \
touch:test${STAGE}${LIBS}${BUILD_TYPE}UnitTest \
touch:lint${STAGE}${LIBS}${BUILD_TYPE} \
leanback:test${STAGE}${LIBS}${BUILD_TYPE}UnitTest \
leanback:lint${STAGE}${LIBS}${BUILD_TYPE}
- store_artifacts:
path: common/build/outputs
destination: common-reports
- store_artifacts:
path: touch/build/outputs
destination: touch
- store_artifacts:
path: touch/build/outputs
destination: touch-reports
- run:
name: Build Leanback
command: |
./gradlew $KEY_CONFIG $SIGN_CONFIG \
-PversionCode=$VERSION_CODE_LEANBACK \
-PversionName=${VERSION_NAME} \
leanback:assemble${STAGE_LOWER}${LIBS}${BUILD_TYPE}
- store_artifacts:
path: leanback/build/outputs
destination: leanback
- save_cache:
<<: *general_cache_key
paths:
- "~/.gradle"
- "~/.m2"
- "/opt/android-sdk-linux/licenses/"
- persist_to_workspace:
root: *workspace_root
paths:
- .
check:
<<: *container_config
parallelism: 1 #4
steps:
- *attach_workspace
- restore_cache:
<<: *general_cache_key
- run:
<<: *setup_env
- run:
name: Lint Common
command: |
./gradlew $KEY_CONFIG \
-PversionCode=$VERSION_CODE_LEANBACK \
-PversionName=${VERSION_NAME} \
common:lint${STAGE}${LIBS}${BUILD_TYPE}
- run:
name: Lint Touch
command: |
./gradlew $KEY_CONFIG \
-PversionCode=$VERSION_CODE_LEANBACK \
-PversionName=${VERSION_NAME} \
touch:lint${STAGE}${LIBS}${BUILD_TYPE}
- run:
name: Lint Leanback
command: |
./gradlew $KEY_CONFIG \
-PversionCode=$VERSION_CODE_LEANBACK \
-PversionName=${VERSION_NAME} \
leanback:lint${STAGE}${LIBS}${BUILD_TYPE} \
- run:
name: Ktlint
command: |
./gradlew $KEY_CONFIG \
-PversionCode=$VERSION_CODE_LEANBACK \
-PversionName=${VERSION_NAME} \
ktlintCheck
- store_artifacts:
path: leanback/build/reports
destination: leanback-reports
path: common/build/reports/
destination: lint_reports/common/
- store_artifacts:
path: common/build/reports/ktlint/
destination: ktlint-reports
path: touch/build/reports/
destination: lint_reports/touch/
- store_artifacts:
path: leanback/build/reports/
destination: lint_reports/leanback/
test:
<<: *container_config
steps:
- *attach_workspace
- restore_cache:
<<: *general_cache_key
- run:
<<: *setup_env
- run:
name: Test Common
command: |
./gradlew $KEY_CONFIG common:test${STAGE}${LIBS}${BUILD_TYPE}UnitTest
- run:
name: Test Touch
command: |
./gradlew $KEY_CONFIG \
-PversionCode=$VERSION_CODE_TOUCH \
-PversionName=${VERSION_NAME} \
touch:test${STAGE}${LIBS}${BUILD_TYPE}UnitTest
- run:
name: Test Leanback
command: |
./gradlew $KEY_CONFIG \
-PversionCode=$VERSION_CODE_LEANBACK \
-PversionName=${VERSION_NAME} \
leanback:test${STAGE}${LIBS}${BUILD_TYPE}UnitTest \
- store_test_results:
path: common/build/test-results
- store_test_results:
path: touch/build/test-results
- store_test_results:
path: leanback/build/test-results
publish-appcenter:
<<: *container_config
steps:
- *attach_workspace
- restore_cache:
<<: *general_cache_key
- run:
name: Appcenter Upload
<<: *setup_env
- run:
name: Touch Appcenter Upload
command: |
git log --format="%h %s" master..HEAD > $RELEASENOTES_FILE
.circleci/appCenterUpload.sh \
@ -104,7 +205,71 @@ jobs:
"touch/build/outputs/mapping/${STAGE_LOWER}${LIBS}/${BUILD_TYPE_LOWER}/mapping.txt" \
"$VERSION_CODE_TOUCH" \
"$VERSION_NAME"
- save_cache:
paths:
- ~/.gradle
key: jars-{{ checksum "build.gradle" }}-{{ checksum "touch/build.gradle" }}-{{ checksum "leanback/build.gradle" }}-{{ checksum "common/build.gradle" }}
- run:
name: Leanback Appcenter Upload
command: |
git log --format="%h %s" master..HEAD > $RELEASENOTES_FILE
.circleci/appCenterUpload.sh \
$APPCENTER_OWNER \
$APPCENTER_TOKEN \
"leanback/build/outputs/apk/${STAGE_LOWER}${LIBS}/${BUILD_TYPE_LOWER}/touch-${STAGE_LOWER}-${LIBS_LOWER}-${BUILD_TYPE_LOWER}.apk" \
$RELEASENOTES_FILE \
$APPCENTER_GROUP \
"leanback/build/outputs/mapping/${STAGE_LOWER}${LIBS}/${BUILD_TYPE_LOWER}/mapping.txt" \
"$VERSION_CODE_LEANBACK" \
"$VERSION_NAME"
publish-play:
<<: *container_config
steps:
- *attach_workspace
- restore_cache:
<<: *general_cache_key
- run:
<<: *setup_env
- run:
name: Setup environment
command: .circleci/setup_env.sh >> $BASH_ENV
- run:
name: Touch Playstore Upload
command: |
echo "$ENCODED_PLAY_CREDENTIALS" | base64 --decode > ./chaosflix-d1d09f33cbb2.json
./gradlew $KEY_CONFIG \
-PversionCode=$VERSION_CODE_TOUCH \
-PversionName=${VERSION_NAME} \
touch:publishApk
workflows:
version: 2
build_test_publish:
jobs:
- build
- check:
requires:
- build
- test:
requires:
- build
- publish-appcenter:
requires:
- test
- check
filters:
branches:
only:
- master
- develop
- publish-play:
requires:
- test
- check
filters:
branches:
only:
- master

View file

@ -15,9 +15,10 @@ echo "export LIBS_LOWER=\"$(tr '[:upper:]' '[:lower:]' <<< ${LIBS:0:1})${LIBS:1}
echo "$ENCODED_KEYSTORE" | base64 --decode > ${HOME}/code/keystore.jks
KEYSTORE=${HOME}/code/keystore.jks
echo "export SIGN_CONFIG=\"-PchaosflixKeystore=$KEYSTORE\
-PchaosflixStorePassword=$KEYSTORE_PASSWORD\
-PchaosflixKeyName=$KEY_NAME\
-PchaosflixKeyPassword=$KEYSTORE_PASSWORD\
-PappcenterId=$APPCENTER_ID\
echo "export KEY_CONFIG=\"-PappcenterId=$APPCENTER_ID\
-PappcenterDevId=$APPCENTER_DEV_ID\""
echo "export SIGN_CONFIG=\"-PchaosflixKeystore=$KEYSTORE \
-PchaosflixStorePassword=$KEYSTORE_PASSWORD \
-PchaosflixKeyName=$KEY_NAME \
-PchaosflixKeyPassword=$KEYSTORE_PASSWORD\""

3
.gitignore vendored
View file

@ -62,4 +62,5 @@ freeline_project_description.json
common/release
touch/release
leanback/release
leanback/release
chaosflix-d1d09f33cbb2.json

View file

@ -11,7 +11,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jlleitschuh.gradle:ktlint-gradle:8.0.0"
classpath "org.jlleitschuh.gradle:ktlint-gradle:9.1.1"
classpath "de.mannodermaus.gradle.plugins:android-junit5:1.5.2.0"
// NOTE: Do not place your application dependencies here; they belong
@ -31,9 +31,6 @@ allprojects {
ext{
touchVersionCode = 1
leanbackVersionCode = 1
minSDK = 22
targetSDK = 28
compileSdkVersion = 28
@ -51,4 +48,3 @@ apply plugin: "org.jlleitschuh.gradle.ktlint-idea"
subprojects {
apply plugin: "org.jlleitschuh.gradle.ktlint"
}

View file

@ -32,6 +32,10 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
abortOnError false
}
buildTypes {
debug {
minifyEnabled false
@ -48,43 +52,59 @@ android {
productFlavors {
prod {
dimension "stage"
if (project.hasProperty('appcenterId')){
buildConfigField "String", "APPCENTER_ID", "$appcenterId"
} else {
buildConfigField "String", "APPCENTER_ID", "\"\""
}
}
dev {
dimension "stage"
if (project.hasProperty('appcenterDevId')){
buildConfigField "String", "APPCENTER_ID", "$appcenterDevId"
} else {
buildConfigField "String", "APPCENTER_ID", "\"\""
}
}
mock {
dimension "stage"
if (project.hasProperty('appcenterDevId')){
buildConfigField "String", "APPCENTER_ID", "$appcenterDevId"
} else {
buildConfigField "String", "APPCENTER_ID", "\"\""
}
buildConfigField "String", "STREAMING_API_BASE_URL", "\"https://gist.githubusercontent.com\""
buildConfigField "String", "STREAMING_API_OFFERS_PATH", "\"/NiciDieNase/1ca017f180242f0ee683a1f592efc4ed/raw/0104592b57f4b29863fd0684a510462af276f30e/example_streams_v2.json\""
}
free {
dimension "libs"
ext {
prod = null
dev = null
mock = null
}
}
noFree{
dimension "libs"
ext {
if(project.hasProperty("appcenterId")){
prod = appcenterId
} else {
prod = null
println "AppcenterId not set"
}
if(project.hasProperty("appcenterDevId")){
dev = appcenterDevId
mock = appcenterDevId
} else {
dev = null
mock = null
println "AppcenterId not set"
}
}
}
}
libraryVariants.all { variant ->
def flavors = variant.productFlavors
// flavorDimensions "stage" -> 0, "libs" -> 1
def stage = flavors[0]
def libs = flavors[1]
variant.buildConfigField "String", "APPCENTER_ID", "${libs[stage.name]}"
}
variantFilter { variant ->
def names = variant.flavors*.name
if (name.contains("prod") && name.contains("Debug")){
setIgnore(true)
}

View file

@ -6,4 +6,4 @@ object BuildTypeInit : ChaosflixInitializer {
override fun init(chaosflixApplication: ChaosflixApplication) {
Stetho.initializeWithDefaults(chaosflixApplication)
}
}
}

View file

@ -3,4 +3,4 @@ import de.nicidienase.chaosflix.ChaosflixInitializer
object LibsInit : ChaosflixInitializer {
override fun init(chaosflixApplication: ChaosflixApplication) {}
}
}

View file

@ -25,4 +25,4 @@ class ChaosflixLoadingSpinner(context: Context, attributeSet: AttributeSet) : Im
anim.repeatCount = Animation.INFINITE
animation = anim
}
}
}

View file

@ -8,4 +8,4 @@ interface AnalyticsWrapper {
fun startAnalytics()
fun stopAnalytics()
}
}

View file

@ -1,22 +1,22 @@
package de.nicidienase.chaosflix.common
import androidx.sqlite.db.SupportSQLiteDatabase
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.room.migration.Migration
import android.content.Context
import androidx.sqlite.db.SupportSQLiteDatabase
import de.nicidienase.chaosflix.common.mediadata.entities.Converters
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.ConferenceDao
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.ConferenceGroup
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.ConferenceGroupDao
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.EventDao
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.EventDao
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Recording
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.RelatedEvent
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.RecordingDao
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.RelatedEvent
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.RelatedEventDao
import de.nicidienase.chaosflix.common.userdata.entities.download.OfflineEvent
import de.nicidienase.chaosflix.common.userdata.entities.download.OfflineEventDao
@ -101,4 +101,4 @@ abstract class ChaosflixDatabase : RoomDatabase() {
}
}
}
}
}

View file

@ -112,4 +112,4 @@ object ChaosflixUtil {
private const val HD_WEBM = "HD-video/webm"
private const val SD_MP4 = "SD-video/mp4"
private const val SD_WEBM = "SD-video/webm"
}
}

View file

@ -2,9 +2,9 @@ package de.nicidienase.chaosflix.common
import android.content.pm.PackageManager
import android.os.Build
import androidx.fragment.app.Fragment
import androidx.core.content.ContextCompat
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
fun androidx.fragment.app.Fragment.checkPermission(permission: String, requestCode: Int, action: () -> Unit) {
if (ContextCompat.checkSelfPermission(requireContext(), permission)
@ -25,4 +25,4 @@ fun AppCompatActivity.checkPermission(permission: String, requestCode: Int, acti
} else {
action()
}
}
}

View file

@ -22,13 +22,13 @@ import de.nicidienase.chaosflix.common.userdata.entities.download.OfflineEvent
import de.nicidienase.chaosflix.common.userdata.entities.download.OfflineEventDao
import de.nicidienase.chaosflix.common.util.LiveEvent
import de.nicidienase.chaosflix.common.viewmodel.DetailsViewModel
import java.io.File
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
class OfflineItemManager(
context: Context,
@ -212,4 +212,4 @@ class OfflineItemManager(
enum class State {
Downloading, Done, PermissionRequired
}
}
}

View file

@ -27,4 +27,4 @@ class PreferencesManager(val sharedPref: SharedPreferences) {
private val keyAnalyticsDisabled = "disable_analytics"
private val keyDownloadFolder = "download_folder"
}
}
}

View file

@ -8,4 +8,4 @@ class ResourcesFacade(context: Context) {
private val resources: Resources = context.applicationContext.resources
fun getString(@StringRes id: Int, vararg any: Any): String = resources.getString(id, any)
}
}

View file

@ -46,4 +46,4 @@ open class SingletonHolder2<out T, in A, in B>(creator: (A, B) -> T) {
}
}
}
}
}

View file

@ -23,12 +23,12 @@ import de.nicidienase.chaosflix.common.userdata.entities.watchlist.WatchlistItem
import de.nicidienase.chaosflix.common.util.ConferenceUtil
import de.nicidienase.chaosflix.common.util.LiveEvent
import de.nicidienase.chaosflix.common.util.SingleLiveEvent
import java.io.IOException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import retrofit2.Response
import java.io.IOException
class MediaRepository(
private val recordingApi: RecordingService,
@ -217,6 +217,12 @@ class MediaRepository(
return event
}
suspend fun findConferenceForUri(data: Uri): Conference? {
val conference =
conferenceDao.findConferenceByAcronymSuspend(data.lastPathSegment)
return conference
}
suspend fun findEventByTitle(title: String): Event? {
var event: Event? = eventDao.findEventByTitleSuspend(title)
if (event == null) {
@ -273,4 +279,4 @@ class MediaRepository(
enum class State {
DONE, RUNNING
}
}
}

View file

@ -3,4 +3,4 @@ package de.nicidienase.chaosflix.common.mediadata.entities.recording
import androidx.annotation.Keep
@Keep
class EventsResponse(var events: List<EventDto>)
class EventsResponse(var events: List<EventDto>)

View file

@ -33,4 +33,4 @@ data class RelatedEventDto(
return arrayOfNulls(size)
}
}
}
}

View file

@ -37,4 +37,4 @@ abstract class BaseDao<in T> {
}
protected abstract suspend fun updateOrInsertInternal(item: T)
}
}

View file

@ -1,11 +1,11 @@
package de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence
import android.os.Parcel
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.Index
import androidx.room.PrimaryKey
import android.os.Parcel
import android.os.Parcelable
import de.nicidienase.chaosflix.common.mediadata.entities.recording.ConferenceDto
@Entity(tableName = "conference",
@ -97,4 +97,4 @@ data class Conference(
return arrayOfNulls(size)
}
}
}
}

View file

@ -1,11 +1,11 @@
package de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence
import android.os.Parcel
import android.os.Parcelable
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import android.os.Parcel
import android.os.Parcelable
@Entity(
tableName = "conference_group",
@ -45,4 +45,4 @@ data class ConferenceGroup(
return arrayOfNulls(size)
}
}
}
}

View file

@ -31,4 +31,4 @@ abstract class ConferenceGroupDao : BaseDao<ConferenceGroup>() {
}
}
}
}
}

View file

@ -1,14 +1,14 @@
package de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence
import android.os.Parcel
import android.os.Parcelable
import android.text.Html
import android.text.Spanned
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Ignore
import androidx.room.Index
import androidx.room.PrimaryKey
import android.os.Parcel
import android.os.Parcelable
import android.text.Html
import android.text.Spanned
import de.nicidienase.chaosflix.common.mediadata.entities.recording.EventDto
@Entity(tableName = "event",
@ -164,4 +164,4 @@ data class Event(
return arrayOfNulls(size)
}
}
}
}

View file

@ -80,4 +80,4 @@ abstract class EventDao : BaseDao<Event>() {
}
}
}
}
}

View file

@ -1,12 +1,12 @@
package de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence
import android.os.Parcel
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Ignore
import androidx.room.Index
import androidx.room.PrimaryKey
import android.os.Parcel
import android.os.Parcelable
import de.nicidienase.chaosflix.common.mediadata.entities.recording.RecordingDto
@Entity(tableName = "recording",
@ -118,4 +118,4 @@ data class Recording(
return arrayOfNulls(size)
}
}
}
}

View file

@ -44,4 +44,4 @@ abstract class RecordingDao : BaseDao<Recording>() {
}
}
}
}
}

View file

@ -1,12 +1,12 @@
package de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence
import android.os.Parcel
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Ignore
import androidx.room.Index
import androidx.room.PrimaryKey
import android.os.Parcel
import android.os.Parcelable
import de.nicidienase.chaosflix.common.mediadata.entities.recording.RelatedEventDto
@Entity(tableName = "related",
@ -58,4 +58,4 @@ data class RelatedEvent(
return arrayOfNulls(size)
}
}
}
}

View file

@ -85,4 +85,4 @@ data class Room(
return dummy
}
}
}
}

View file

@ -6,13 +6,13 @@ import com.google.gson.Gson
import de.nicidienase.chaosflix.BuildConfig
import de.nicidienase.chaosflix.R
import de.nicidienase.chaosflix.common.SingletonHolder2
import java.io.File
import java.util.concurrent.TimeUnit
import okhttp3.Cache
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.util.concurrent.TimeUnit
class ApiFactory private constructor(res: Resources, cache: File) {
@ -63,4 +63,4 @@ class ApiFactory private constructor(res: Resources, cache: File) {
return "chaosflix/$versionName $osVersion ($device)"
}
}
}
}

View file

@ -44,4 +44,4 @@ interface RecordingService {
@GET("public/events/{guid}")
suspend fun getEventByGUIDSuspending(@Path("guid") guid: String): EventDto?
}
}

View file

@ -1,12 +1,12 @@
package de.nicidienase.chaosflix.common.userdata.entities.download
import android.os.Parcel
import android.os.Parcelable
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.Index
import androidx.room.PrimaryKey
import android.os.Parcel
import android.os.Parcelable
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Recording
@ -56,4 +56,4 @@ data class OfflineEvent(
return arrayOfNulls(size)
}
}
}
}

View file

@ -40,4 +40,4 @@ interface OfflineEventDao {
@Query("SELECT o.event_guid,o.recording_id,o.download_reference,o.local_path,e.title,e.subtitle,e.length,e.thumbUrl FROM offline_event o JOIN event e WHERE o.event_guid = e.guid")
fun getOfflineEventsDisplay(): LiveData<List<OfflineEventView>>
}
}

View file

@ -1,7 +1,7 @@
package de.nicidienase.chaosflix.common.userdata.entities.download
import androidx.room.ColumnInfo
import androidx.annotation.Keep
import androidx.room.ColumnInfo
@Keep
data class OfflineEventView(
@ -13,4 +13,4 @@ data class OfflineEventView(
@ColumnInfo(name = "subtitle") var subtitle: String?,
@ColumnInfo(name = "length") val length: Long,
@ColumnInfo(name = "thumbUrl") var thumbUrl: String
)
)

View file

@ -25,4 +25,4 @@ interface PlaybackProgressDao {
@Query("DELETE from playback_progress WHERE event_guid = :guid")
fun deleteItem(guid: String)
}
}

View file

@ -2,10 +2,10 @@ package de.nicidienase.chaosflix.common.userdata.entities.watchlist
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Query
import androidx.room.OnConflictStrategy
import androidx.room.Insert
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.BaseDao
@Dao
@ -45,4 +45,4 @@ abstract class WatchlistItemDao : BaseDao<WatchlistItem>() {
}
}
}
}
}

View file

@ -41,4 +41,4 @@ object ConferenceUtil {
"fiffkon",
"cryptocon"
)
}
}

View file

@ -16,4 +16,4 @@ class LiveDataMerger<T, U, R> {
}
return result
}
}
}

View file

@ -4,4 +4,4 @@ class LiveEvent<T, U, V>(
val state: T,
val data: U? = null,
val error: V? = null
)
)

View file

@ -16,12 +16,11 @@
package de.nicidienase.chaosflix.common.util
import android.util.Log
import androidx.annotation.MainThread
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.annotation.MainThread
import android.util.Log
import java.util.concurrent.atomic.AtomicBoolean
/**
@ -73,4 +72,4 @@ class SingleLiveEvent<T> : MutableLiveData<T>() {
private val TAG = "SingleLiveEvent"
}
}
}

View file

@ -11,8 +11,8 @@ import de.nicidienase.chaosflix.common.PreferencesManager
import de.nicidienase.chaosflix.common.ResourcesFacade
import de.nicidienase.chaosflix.common.mediadata.MediaRepository
import de.nicidienase.chaosflix.common.mediadata.StreamingRepository
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.ConferenceGroup
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.ConferenceGroup
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.mediadata.entities.streaming.LiveConference
import de.nicidienase.chaosflix.common.util.LiveDataMerger

View file

@ -14,9 +14,9 @@ import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.
import de.nicidienase.chaosflix.common.userdata.entities.watchlist.WatchlistItem
import de.nicidienase.chaosflix.common.util.LiveEvent
import de.nicidienase.chaosflix.common.util.SingleLiveEvent
import java.io.File
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
class DetailsViewModel(
private val database: ChaosflixDatabase,

View file

@ -5,9 +5,9 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import de.nicidienase.chaosflix.common.ChaosflixDatabase
import de.nicidienase.chaosflix.common.userdata.entities.progress.PlaybackProgress
import java.util.Date
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.Date
class PlayerViewModel(val database: ChaosflixDatabase) : ViewModel() {

View file

@ -11,13 +11,13 @@ import de.nicidienase.chaosflix.common.mediadata.MediaRepository
import de.nicidienase.chaosflix.common.userdata.entities.watchlist.WatchlistItem
import de.nicidienase.chaosflix.common.userdata.entities.watchlist.WatchlistItemDao
import de.nicidienase.chaosflix.common.util.LiveEvent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.File
import java.io.FileReader
import java.io.FileWriter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class PreferencesViewModel(
private val mediaRepository: MediaRepository,
@ -94,4 +94,4 @@ class PreferencesViewModel(
private val TAG = PreferencesViewModel::class.java.simpleName
private const val FAVORITES_FILENAME = "chaosflix_favorites.json"
}
}
}

View file

@ -7,15 +7,15 @@ import de.nicidienase.chaosflix.common.mediadata.MediaRepository
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.util.LiveEvent
import de.nicidienase.chaosflix.common.util.SingleLiveEvent
import java.lang.Exception
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.lang.Exception
class SplashViewModel(
private val mediaRepository: MediaRepository
) : ViewModel() {
val state: SingleLiveEvent<LiveEvent<State, Event, Exception>> = SingleLiveEvent()
val state: SingleLiveEvent<LiveEvent<State, Any, Exception>> = SingleLiveEvent()
fun findEventForUri(data: Uri) = viewModelScope.launch(Dispatchers.IO) {
try {
@ -30,8 +30,21 @@ class SplashViewModel(
}
}
fun findConferenceForUri(data: Uri) = viewModelScope.launch(Dispatchers.IO) {
try {
val conference = mediaRepository.findConferenceForUri(data)
if (conference != null) {
state.postValue(LiveEvent(State.FOUND, conference))
} else {
state.postValue(LiveEvent(State.NOT_FOUND))
}
} catch (ex: Exception) {
state.postValue(LiveEvent(State.NOT_FOUND, error = ex))
}
}
enum class State {
FOUND,
NOT_FOUND
}
}
}

View file

@ -13,4 +13,4 @@ object LibsInit : ChaosflixInitializer {
AnalyticsWrapperImpl.init(chaosflixApplication)
}
}
}
}

View file

@ -21,11 +21,11 @@ object AnalyticsWrapperImpl : AnalyticsWrapper {
override fun startAnalytics() {
Analytics.setEnabled(true)
// Crashes.setEnabled(true)
Crashes.setEnabled(true)
}
override fun stopAnalytics() {
Analytics.setEnabled(false)
// Crashes.setEnabled(false)
Crashes.setEnabled(false)
}
}

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="privacy_policy">Chaosflix does not collect or transmit any personalized data.\n\nFor statistical and troubleshooting purposes an anonymous ID, type, version and language of the device, service life and crash logs are collected using Microsoft Visual Studio App Center.</string>
<string name="privacy_policy">Chaosflix does not collect or transmit any personalized data.\n\nFor statistical and troubleshooting purposes an anonymous ID, type, version and language of the device, service life and crash logs are collected using Microsoft Visual Studio App Center.\nThis can be disable in preferences.</string>
</resources>

View file

@ -3,4 +3,4 @@ import de.nicidienase.chaosflix.ChaosflixInitializer
object StageInit : ChaosflixInitializer {
override fun init(chaosflixApplication: ChaosflixApplication) {}
}
}

View file

@ -30,4 +30,4 @@ class ConferencesWrapperTest {
)
assert(wrapper.conferencesMap.keys.size == 1)
}
}
}

View file

@ -1,6 +1,7 @@
#Sun Nov 10 22:16:34 CET 2019
#Mon Feb 03 20:13:07 CET 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
distributionSha256Sum=10065868c78f1207afb3a92176f99a37d753a513dff453abb6b5cceda4058cda

View file

@ -1,7 +1,10 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'kotlin-android-extensions'
id 'com.github.triplet.play' version '2.6.2'
}
String appName = "Chaosflix"
String versionString = new File("versionfile").text.trim()
@ -16,7 +19,7 @@ android {
minSdkVersion rootProject.ext.minSDK
targetSdkVersion rootProject.ext.targetSDK
// odd for touch, even for leanback
versionCode rootProject.ext.leanbackVersionCode
versionCode 1
versionName versionString
if(project.hasProperty("versionCode")){
versionCode = project.property("versionCode") as int
@ -101,6 +104,11 @@ android {
lintOptions.abortOnError = false
dataBinding.enabled = true
buildToolsVersion rootProject.ext.buildToolsVersion
playConfigs {
prodNoFree {
enabled = true
}
}
}
configurations {
@ -127,3 +135,10 @@ dependencies {
androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.6.0'
}
play {
serviceAccountCredentials = file("../chaosflix-d1d09f33cbb2.json")
track = "Alpha"
enabled = false
}

View file

@ -1,13 +1,13 @@
package de.nicidienase.chaosflix.leanback
import android.os.Bundle
import androidx.leanback.app.ErrorSupportFragment
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.leanback.app.ErrorSupportFragment
class BrowseErrorFragment : ErrorSupportFragment() {
private var spinnerFragment: SpinnerFragment? = null

View file

@ -18,4 +18,4 @@ class ChaosflixEventAdapter(presenter: Presenter) : ArrayObjectAdapter(presenter
-1
}
}
}
}

View file

@ -24,4 +24,4 @@ object DiffCallbacks {
return oldItem.updatedAt == newItem.updatedAt
}
}
}
}

View file

@ -1,12 +1,12 @@
package de.nicidienase.chaosflix.leanback
import android.content.Context
import androidx.leanback.widget.Presenter
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.leanback.widget.Presenter
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.mediadata.entities.streaming.Room
import de.nicidienase.chaosflix.leanback.databinding.DetailViewBinding

View file

@ -1,8 +1,7 @@
package de.nicidienase.chaosflix.leanback.conferences
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import android.os.Bundle
import android.util.Log
import androidx.leanback.app.BrowseSupportFragment
import androidx.leanback.widget.ArrayObjectAdapter
import androidx.leanback.widget.DividerRow
@ -11,7 +10,8 @@ import androidx.leanback.widget.ListRow
import androidx.leanback.widget.ListRowPresenter
import androidx.leanback.widget.Row
import androidx.leanback.widget.SectionRow
import android.util.Log
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import de.nicidienase.chaosflix.common.mediadata.MediaRepository
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.ConferenceGroup

View file

@ -7,9 +7,9 @@ import android.graphics.Color
import android.graphics.Paint
import android.media.MediaMetadataRetriever
import android.os.Build
import android.util.Log
import androidx.leanback.media.PlaybackGlue
import androidx.leanback.widget.PlaybackSeekDataProvider
import android.util.Log
import de.nicidienase.chaosflix.common.mediadata.network.ApiFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -212,4 +212,4 @@ class ChaosflixSeekDataProvider(
}
}
}
}
}

View file

@ -3,9 +3,8 @@ package de.nicidienase.chaosflix.leanback.detail
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.FragmentActivity
import android.view.WindowManager
import androidx.fragment.app.FragmentActivity
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.mediadata.entities.streaming.Room
import de.nicidienase.chaosflix.leanback.R

View file

@ -1,8 +1,6 @@
package de.nicidienase.chaosflix.leanback.detail
import android.app.AlertDialog
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
@ -12,6 +10,10 @@ import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.text.TextUtils
import android.util.Log
import android.view.View
import androidx.core.content.ContextCompat
import androidx.leanback.app.DetailsSupportFragment
import androidx.leanback.app.DetailsSupportFragmentBackgroundController
import androidx.leanback.widget.Action
@ -24,10 +26,8 @@ import androidx.leanback.widget.HeaderItem
import androidx.leanback.widget.ListRow
import androidx.leanback.widget.ListRowPresenter
import androidx.leanback.widget.OnActionClickedListener
import androidx.core.content.ContextCompat
import android.text.TextUtils
import android.util.Log
import android.view.View
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget
@ -405,4 +405,4 @@ class EventDetailsFragment : DetailsSupportFragment() {
builder.create().show()
}
}
}
}

View file

@ -1,11 +1,11 @@
package de.nicidienase.chaosflix.leanback.events
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import de.nicidienase.chaosflix.common.mediadata.MediaRepository
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event

View file

@ -3,6 +3,9 @@ package de.nicidienase.chaosflix.leanback.events
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.os.Handler
import android.util.DisplayMetrics
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.leanback.app.BackgroundManager
import androidx.leanback.app.VerticalGridSupportFragment
import androidx.leanback.widget.ArrayObjectAdapter
@ -12,9 +15,6 @@ import androidx.leanback.widget.Presenter
import androidx.leanback.widget.Row
import androidx.leanback.widget.RowPresenter
import androidx.leanback.widget.VerticalGridPresenter
import androidx.core.content.ContextCompat
import android.util.DisplayMetrics
import android.util.Log
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget

View file

@ -3,6 +3,9 @@ package de.nicidienase.chaosflix.leanback.events
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.os.Handler
import android.util.DisplayMetrics
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.leanback.app.BackgroundManager
import androidx.leanback.app.BrowseSupportFragment
import androidx.leanback.widget.ArrayObjectAdapter
@ -13,9 +16,6 @@ import androidx.leanback.widget.OnItemViewSelectedListener
import androidx.leanback.widget.Presenter
import androidx.leanback.widget.Row
import androidx.leanback.widget.RowPresenter
import androidx.core.content.ContextCompat
import android.util.DisplayMetrics
import android.util.Log
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget

View file

@ -1,7 +1,10 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'kotlin-android-extensions'
id 'com.github.triplet.play' version '2.6.2'
}
String appName = "Chaosflix"
String versionString = new File("versionfile").text.trim()
@ -17,7 +20,7 @@ android {
targetSdkVersion rootProject.ext.targetSDK
manifestPlaceholders = [label: appName]
// odd for touch, even for leanback
versionCode rootProject.ext.touchVersionCode
versionCode 1
versionName versionString
if(project.hasProperty("versionCode")){
@ -57,6 +60,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
if (project.hasProperty("chaosflixKeystore") && file(chaosflixKeystore).exists() && file(chaosflixKeystore).isFile()) {
signingConfig signingConfigs.release
}
}
@ -110,6 +114,12 @@ android {
lintOptions.abortOnError false
dataBinding.enabled = true
testOptions.unitTests.includeAndroidResources = true
playConfigs {
prodNoFreeRelease {
enabled = true
}
}
}
configurations {
@ -153,4 +163,12 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0', {
exclude group: 'com.android.support', module: 'support-annotations'
}
}
}
play {
serviceAccountCredentials = file("../chaosflix-d1d09f33cbb2.json")
track = "alpha"
releaseStatus = "draft"
enabled = false
artifactDir = file("build/outputs/apk/prodNoFree/release/touch-prod-noFree-release.apk")
}

View file

@ -4,9 +4,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import de.nicidienase.chaosflix.common.ChaosflixDatabase
import de.nicidienase.chaosflix.common.userdata.entities.progress.PlaybackProgress
import java.util.Date
import org.junit.Test
import org.junit.runner.RunWith
import java.util.Date
/**
* Created by felix on 31.10.17.

View file

@ -8,6 +8,7 @@ import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.
import de.nicidienase.chaosflix.common.mediadata.entities.streaming.StreamUrl
import de.nicidienase.chaosflix.touch.browse.streaming.StreamingItem
@SuppressWarnings("unused")
class CastService(activity: Activity, withMiniController: Boolean = true) {
val connected: Boolean = false
@ -27,4 +28,4 @@ class CastService(activity: Activity, withMiniController: Boolean = true) {
companion object {
val TAG = CastService::class.java.simpleName
}
}
}

View file

@ -0,0 +1,14 @@
Schaue Aufzeichnungen und Streams von media.ccc.de auf deinem Smartphone, Tablet oder AndroidTV-Gerät.
Features:
<ul>
<li>Livestreams</li>
<li>Talks als Lesezeichen Speichern</li>
<li>Talks zum offline Schauen herunterladen</li>
</ul>
Chromecast-Unterstützung fehlt leider in der Version auf F-Droid, da hierfür unfreie Bibliotheken nötig sind.
Die Version für Fernseher (AndroidTV und FireTV) ist zur Zeit nicht auf F-Droid
Bugreports, Verbesserungsvorschläge, etc. sind willkommen: https://github.com/NiciDieNase/chaosflix/issues

View file

@ -0,0 +1,14 @@
Watch streams and recordings from media.ccc.de on your phone or tablet.
Features:
<ul>
<li>Livestreams</li>
<li>Bookmarking Talks</li>
<li>Download Talks for offline viewing</li>
</ul>
Chromecast support is not available for the version on F-Droid, since it requires non-free libraries.
There is also a version for TVs (AndroidTV and FireTV) which is current not on F-Droid.
Suggestions, Bugreports, etc. are welcome on https://github.com/NiciDieNase/chaosflix/issues

View file

@ -37,6 +37,10 @@
android:scheme="https"
android:host="media.ccc.de"
android:pathPrefix="/v/"/>
<data
android:scheme="https"
android:host="media.ccc.de"
android:pathPrefix="/c/"/>
</intent-filter>
</activity>
<activity android:name=".browse.BrowseActivity">

View file

@ -1,12 +1,12 @@
package de.nicidienase.chaosflix.touch
import androidx.databinding.BindingAdapter
import android.widget.ImageView
import android.widget.TextView
import androidx.databinding.BindingAdapter
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
@BindingAdapter("bind:imageUrl")
@BindingAdapter("imageUrl")
fun loadImage(imageView: ImageView, url: String?) {
if (url == null) return
Glide.with(imageView.context)
@ -15,7 +15,7 @@ fun loadImage(imageView: ImageView, url: String?) {
.into(imageView)
}
@BindingAdapter("bind:time")
@BindingAdapter("time")
fun setDuration(textView: TextView, duration: Long) {
textView.text = String.format("%d:%02d:%02d", duration / 3600, (duration % 3600) / 60, duration % 60)
}
}

View file

@ -4,4 +4,4 @@ import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.
interface OnEventSelectedListener {
fun onEventSelected(event: Event)
}
}

View file

@ -6,10 +6,12 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.viewmodel.SplashViewModel
import de.nicidienase.chaosflix.common.viewmodel.ViewModelFactory
import de.nicidienase.chaosflix.touch.browse.BrowseActivity
import de.nicidienase.chaosflix.touch.browse.eventslist.EventsListActivity
import de.nicidienase.chaosflix.touch.eventdetails.EventDetailsActivity
class SplashActivity : AppCompatActivity() {
@ -37,11 +39,10 @@ class SplashActivity : AppCompatActivity() {
viewModel.state.observe(this, Observer {
when (it.state) {
SplashViewModel.State.FOUND -> {
val event = it.data
if (event != null) {
goToEvent(event)
} else {
goToOverview()
when (val item = it.data) {
is Event -> goToEvent(item)
is Conference -> goToConference(item)
else -> goToOverview()
}
}
SplashViewModel.State.NOT_FOUND -> {
@ -51,7 +52,10 @@ class SplashActivity : AppCompatActivity() {
})
if (data != null) {
viewModel.findEventForUri(data)
when (data.pathSegments[0]) {
"v" -> viewModel.findEventForUri(data)
"c" -> viewModel.findConferenceForUri(data)
}
} else {
goToOverview()
}
@ -66,4 +70,9 @@ class SplashActivity : AppCompatActivity() {
EventDetailsActivity.launch(this, event)
finish()
}
}
private fun goToConference(conference: Conference) {
EventsListActivity.start(this, conference)
finish()
}
}

View file

@ -1,10 +1,10 @@
package de.nicidienase.chaosflix.touch.about
import androidx.databinding.DataBindingUtil
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import android.view.View
import androidx.databinding.DataBindingUtil
import de.nicidienase.chaosflix.touch.R
import de.nicidienase.chaosflix.touch.databinding.ActivityAboutBinding
import mehdi.sakout.aboutpage.AboutPage

View file

@ -1,10 +1,10 @@
package de.nicidienase.chaosflix.touch.about
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import com.mikepenz.aboutlibraries.LibsBuilder
import com.mikepenz.aboutlibraries.ui.LibsSupportFragment
import de.nicidienase.chaosflix.touch.R
@ -23,4 +23,4 @@ class LibsFragment : androidx.fragment.app.DialogFragment() {
.withFields(R.string::class.java.fields)
.supportFragment()
}
}
}

View file

@ -1,28 +1,28 @@
package de.nicidienase.chaosflix.touch.browse
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.res.Configuration
import androidx.databinding.DataBindingUtil
import android.os.Bundle
import android.os.PersistableBundle
import com.google.android.material.navigation.NavigationView
import com.google.android.material.snackbar.Snackbar
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import android.transition.TransitionInflater
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.google.android.material.navigation.NavigationView
import com.google.android.material.snackbar.Snackbar
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.mediadata.entities.streaming.StreamUrl

View file

@ -1,11 +1,11 @@
package de.nicidienase.chaosflix.touch.browse
import androidx.lifecycle.ViewModelProviders
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import android.view.View
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProviders
import de.nicidienase.chaosflix.common.viewmodel.BrowseViewModel
import de.nicidienase.chaosflix.common.viewmodel.ViewModelFactory

View file

@ -1,8 +1,8 @@
package de.nicidienase.chaosflix.touch.browse.adapters
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.touch.browse.ConferencesTabBrowseFragment
import de.nicidienase.chaosflix.touch.databinding.ItemConferenceCardviewBinding

View file

@ -1,9 +1,9 @@
package de.nicidienase.chaosflix.touch.browse.adapters
import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.RecyclerView
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.touch.databinding.ItemEventCardviewBinding

View file

@ -1,8 +1,8 @@
package de.nicidienase.chaosflix.touch.browse.adapters
import androidx.recyclerview.widget.RecyclerView
import android.widget.Filter
import android.widget.Filterable
import androidx.recyclerview.widget.RecyclerView
import java.util.Collections
abstract class ItemRecyclerViewAdapter<T, VH : RecyclerView.ViewHolder?> :

View file

@ -1,13 +1,13 @@
package de.nicidienase.chaosflix.touch.browse.download
import androidx.lifecycle.Observer
import android.os.Bundle
import android.os.Handler
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import de.nicidienase.chaosflix.touch.R
import de.nicidienase.chaosflix.touch.browse.BrowseFragment
import de.nicidienase.chaosflix.touch.databinding.FragmentDownloadsBinding
@ -84,4 +84,4 @@ class DownloadsListFragment : BrowseFragment() {
return fragment
}
}
}
}

View file

@ -1,15 +1,15 @@
package de.nicidienase.chaosflix.touch.browse.download
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import de.nicidienase.chaosflix.common.OfflineItemManager
import de.nicidienase.chaosflix.touch.R
import de.nicidienase.chaosflix.common.userdata.entities.download.OfflineEventView
import de.nicidienase.chaosflix.touch.R
import de.nicidienase.chaosflix.touch.databinding.ItemOfflineEventBinding
class OfflineEventAdapter(
@ -58,4 +58,4 @@ class OfflineEventAdapter(
inner class ViewHolder(val binding: ItemOfflineEventBinding, val view: View) : RecyclerView.ViewHolder(view) {
val thumbnail = binding.imageView
}
}
}

View file

@ -3,12 +3,12 @@ package de.nicidienase.chaosflix.touch.browse.eventslist
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.view.Menu
import de.nicidienase.chaosflix.touch.R
import androidx.appcompat.app.AppCompatActivity
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.touch.OnEventSelectedListener
import de.nicidienase.chaosflix.touch.R
import de.nicidienase.chaosflix.touch.browse.cast.CastService
import de.nicidienase.chaosflix.touch.eventdetails.EventDetailsActivity

View file

@ -1,9 +1,9 @@
package de.nicidienase.chaosflix.touch.browse.streaming
import androidx.recyclerview.widget.RecyclerView
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import de.nicidienase.chaosflix.common.mediadata.entities.streaming.LiveConference

View file

@ -1,15 +1,15 @@
package de.nicidienase.chaosflix.touch.browse.streaming
import androidx.lifecycle.Observer
import android.content.Context
import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar
import de.nicidienase.chaosflix.touch.R
import de.nicidienase.chaosflix.touch.browse.BrowseFragment
import de.nicidienase.chaosflix.touch.databinding.FragmentLivestreamsBinding
@ -98,4 +98,4 @@ class LivestreamListFragment : BrowseFragment() {
return fragment
}
}
}
}

View file

@ -8,4 +8,4 @@ data class StreamingItem(
val conference: LiveConference,
val group: Group,
val room: Room
)
)

View file

@ -1,8 +1,6 @@
package de.nicidienase.chaosflix.touch.eventdetails
import android.Manifest
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
@ -10,10 +8,12 @@ import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import android.view.Menu
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import android.view.Menu
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.google.android.material.snackbar.Snackbar
import de.nicidienase.chaosflix.common.ChaosflixUtil
import de.nicidienase.chaosflix.common.OfflineItemManager
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event

View file

@ -1,17 +1,9 @@
package de.nicidienase.chaosflix.touch.eventdetails
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.snackbar.Snackbar
import androidx.fragment.app.Fragment
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
@ -19,16 +11,24 @@ import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import de.nicidienase.chaosflix.touch.R
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.snackbar.Snackbar
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.userdata.entities.watchlist.WatchlistItem
import de.nicidienase.chaosflix.common.viewmodel.DetailsViewModel
import de.nicidienase.chaosflix.touch.databinding.FragmentEventDetailsBinding
import de.nicidienase.chaosflix.touch.OnEventSelectedListener
import de.nicidienase.chaosflix.common.viewmodel.ViewModelFactory
import de.nicidienase.chaosflix.touch.OnEventSelectedListener
import de.nicidienase.chaosflix.touch.R
import de.nicidienase.chaosflix.touch.browse.adapters.EventRecyclerViewAdapter
import de.nicidienase.chaosflix.touch.databinding.FragmentEventDetailsBinding
class EventDetailsFragment : androidx.fragment.app.Fragment() {

View file

@ -64,7 +64,7 @@ public class ExoPlayerFragment extends Fragment implements PlayerEventListener.P
private PlayerViewModel viewModel;
private PlaybackItem item;
FragmentExoPlayerBinding binding;
private FragmentExoPlayerBinding binding;
public ExoPlayerFragment() {
}
@ -87,12 +87,12 @@ public class ExoPlayerFragment extends Fragment implements PlayerEventListener.P
playbackState = savedInstanceState.getBoolean(PLAYBACK_STATE, true);
}
viewModel = ViewModelProviders.of(this, ViewModelFactory.Companion.getInstance(requireContext())).get(PlayerViewModel.class);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_exo_player, container, false);
viewModel = ViewModelProviders.of(this, ViewModelFactory.Companion.getInstance(requireContext())).get(PlayerViewModel.class);
Toolbar toolbar = binding.getRoot().findViewById(R.id.toolbar);
toolbar.setTitle(item.getTitle());
@ -170,8 +170,11 @@ public class ExoPlayerFragment extends Fragment implements PlayerEventListener.P
AdaptiveTrackSelection.Factory trackSelectorFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(trackSelectorFactory);
LoadControl loadControl = new DefaultLoadControl();
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(getContext(), null, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF);
DefaultRenderersFactory renderersFactory
= new DefaultRenderersFactory(
getContext(),
null,
DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF);
exoPlayer = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector);

View file

@ -31,4 +31,4 @@ data class PlaybackItem(val title: String, val subtitle: String, val eventGuid:
return arrayOfNulls(size)
}
}
}
}

View file

@ -3,13 +3,13 @@ package de.nicidienase.chaosflix.touch.playback
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem
import de.nicidienase.chaosflix.touch.R
import androidx.appcompat.app.AppCompatActivity
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Recording
import de.nicidienase.chaosflix.common.mediadata.entities.streaming.StreamUrl
import de.nicidienase.chaosflix.touch.R
import de.nicidienase.chaosflix.touch.browse.cast.CastService
class PlayerActivity : AppCompatActivity() {

View file

@ -1,8 +1,8 @@
package de.nicidienase.chaosflix.touch.settings
import androidx.databinding.DataBindingUtil
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import de.nicidienase.chaosflix.touch.R
import de.nicidienase.chaosflix.touch.databinding.ActivitySettingsBinding
@ -15,4 +15,4 @@ class SettingsActivity : AppCompatActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setTitle(R.string.settings)
}
}
}

View file

@ -1,15 +1,15 @@
package de.nicidienase.chaosflix.touch.settings
import android.Manifest
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.snackbar.Snackbar
import de.nicidienase.chaosflix.R
import de.nicidienase.chaosflix.common.checkPermission
import de.nicidienase.chaosflix.common.viewmodel.PreferencesViewModel
@ -177,4 +177,4 @@ class SettingsFragment : PreferenceFragmentCompat() {
return fragment
}
}
}
}

View file

@ -0,0 +1 @@
chaosflix@nicidienase.de

View file

@ -0,0 +1 @@
https://github.com/NiciDieNase/chaosflix

View file

@ -0,0 +1 @@
en-US

View file

@ -0,0 +1,11 @@
Schaue Aufzeichnungen und Streams von media.ccc.de auf deinem Smartphone, Tablet oder AndroidTV-Gerät.
Features:
<ul>
<li>Livestreams</li>
<li>Talks als Lesezeichen Speichern</li>
<li>Talks zum offline Schauen herunterladen</li>
<li>Chromecast-Unterstützung</li>
</ul>
Bugreports, Verbesserungsvorschläge, etc. sind willkommen: https://github.com/NiciDieNase/chaosflix/issues

View file

@ -0,0 +1 @@
Schaue Aufzeichnungen und Streams von media.ccc.de

View file

@ -0,0 +1,11 @@
Watch streams and recordings from media.ccc.de on your phone, tablet or AndroidTV-device
Features:
<ul>
<li>Livestreams</li>
<li>Bookmarking Talks</li>
<li>Download Talks for offline viewing</li>
<li>Watch on Chromecast</li>
</ul>
Suggestions, Bugreports, etc. are welcome on https://github.com/NiciDieNase/chaosflix/issues

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Some files were not shown because too many files have changed in this diff Show more