From 70ae7d07af49261a4b45f7997284d2044984aa4b Mon Sep 17 00:00:00 2001 From: Ken Yee Date: Tue, 27 Mar 2018 21:13:31 -0400 Subject: [PATCH 001/173] fix notifications if user bookmarked multiple sessions; make MainActivity singleTask so it doesn't get created multiple times when user clicks on push notification --- .../app/src/main/AndroidManifest.xml | 4 +++- .../utils/NotificationUtils.kt | 12 +++++----- .../droidcon_boston/views/MainActivity.kt | 24 +++++++++++++++---- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Droidcon-Boston/app/src/main/AndroidManifest.xml b/Droidcon-Boston/app/src/main/AndroidManifest.xml index a10c596..eec4108 100644 --- a/Droidcon-Boston/app/src/main/AndroidManifest.xml +++ b/Droidcon-Boston/app/src/main/AndroidManifest.xml @@ -29,7 +29,9 @@ + android:screenOrientation="portrait" + android:launchMode="singleTask" + android:taskAffinity="" /> = Build.VERSION_CODES.O) { // create android channel val androidChannel = NotificationChannel(ANDROID_CHANNEL_ID, @@ -132,7 +132,7 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { fun enableBootReceiver(context: Context, enabled: Boolean = true) { val receiver = ComponentName(context, BootReceiver::class.java) - val pm = context.getPackageManager() + val pm = context.packageManager pm.setComponentEnabledSetting(receiver, if (enabled) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, @@ -148,21 +148,21 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { .setSmallIcon(R.drawable.ic_notification_session_start) .setAutoCancel(true) + val notificationId = sessionId.hashCode() if (!TextUtils.isEmpty(sessionDetail)) { val sessionIntent = MainActivity.getSessionDetailIntent(this, sessionId, sessionDetail) - val contentIntent = PendingIntent.getActivity(this, 0, + val contentIntent = PendingIntent.getActivity(this, notificationId, sessionIntent, PendingIntent.FLAG_UPDATE_CURRENT) builder.setContentIntent(contentIntent) } val notificationIntent = Intent(this, NotificationPublisher::class.java).apply { - putExtra(NotificationPublisher.NOTIFICATION_ID, sessionId.hashCode()) + putExtra(NotificationPublisher.NOTIFICATION_ID, notificationId) putExtra(NotificationPublisher.SESSION_ID, sessionId) putExtra(NotificationPublisher.NOTIFICATION, builder.build()) } - val pendingIntent = PendingIntent.getBroadcast(this, sessionId.hashCode(), notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT) - return pendingIntent + return PendingIntent.getBroadcast(this, notificationId, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT) } companion object { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index 4324785..7098c77 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -12,6 +12,8 @@ import android.text.TextUtils import android.view.Gravity import android.view.MenuItem import com.mentalmachines.droidcon_boston.R +import com.mentalmachines.droidcon_boston.R.id +import com.mentalmachines.droidcon_boston.R.string import com.mentalmachines.droidcon_boston.data.Schedule.ScheduleRow import com.mentalmachines.droidcon_boston.utils.ServiceLocator import com.mentalmachines.droidcon_boston.views.agenda.AgendaFragment @@ -34,14 +36,26 @@ class MainActivity : AppCompatActivity() { initNavDrawerToggle() - replaceFragment(getString(R.string.str_agenda)) + initFragmentsFromIntent(intent) + } + + private fun initFragmentsFromIntent(initialIntent: Intent) { + replaceFragment(getString(string.str_agenda)) - val sessionDetails = intent.extras?.getString(EXTRA_SESSION_DETAILS) + val sessionDetails = initialIntent.extras?.getString(EXTRA_SESSION_DETAILS) if (!TextUtils.isEmpty(sessionDetails)) { AgendaDetailFragment.addDetailFragmentToStack(supportFragmentManager, ServiceLocator.gson.fromJson(sessionDetails, ScheduleRow::class.java)) } else { - navView.setCheckedItem(R.id.nav_agenda) + navView.setCheckedItem(id.nav_agenda) + } + } + + override fun onNewIntent(intent: Intent?) { + super.onNewIntent(intent) + + intent?.let { + initFragmentsFromIntent(it) } } @@ -239,11 +253,11 @@ class MainActivity : AppCompatActivity() { private const val EXTRA_SESSION_DETAILS = "MainActivity.EXTRA_SESSION_DETAILS" fun getSessionDetailIntent(context: Context, sessionId: String, sessionDetail: String): Intent { - val intent = Intent(context, MainActivity::class.java).apply { + return Intent(context, MainActivity::class.java).apply { putExtra(EXTRA_SESSIONID, sessionId) putExtra(EXTRA_SESSION_DETAILS, sessionDetail) + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP } - return intent } } } From 38875ca3b8b62dfbf96880b0a7bde346ce88bb86 Mon Sep 17 00:00:00 2001 From: Nishant Srivastava Date: Sat, 3 Nov 2018 02:03:56 +0100 Subject: [PATCH 002/173] updated: deps and gradle wrapper --- Droidcon-Boston/.idea/codeStyleSettings.xml | 778 ------------------ Droidcon-Boston/app/build.gradle | 17 +- Droidcon-Boston/build.gradle | 8 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 4 files changed, 12 insertions(+), 793 deletions(-) delete mode 100644 Droidcon-Boston/.idea/codeStyleSettings.xml diff --git a/Droidcon-Boston/.idea/codeStyleSettings.xml b/Droidcon-Boston/.idea/codeStyleSettings.xml deleted file mode 100644 index 61ac0f6..0000000 --- a/Droidcon-Boston/.idea/codeStyleSettings.xml +++ /dev/null @@ -1,778 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index 7f7117e..7d48f6e 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -4,12 +4,12 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'io.fabric' android { - compileSdkVersion 27 + compileSdkVersion 28 defaultConfig { applicationId "com.mentalmachines.droidcon_boston" minSdkVersion 16 - targetSdkVersion 27 + targetSdkVersion 28 versionCode 17 versionName "2.0.9" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -53,16 +53,13 @@ android { } dependencies { - final support = "27.1.0" - final playServices = "11.8.0" - final junit = "4.12" - implementation fileTree(dir: 'libs', include: ['*.jar']) // TESTING - testImplementation "junit:junit:$junit" + testImplementation "junit:junit:4.12" // Support + final support = "28.0.0" implementation "com.android.support:appcompat-v7:$support" implementation "com.android.support:support-v4:$support" implementation "com.android.support:cardview-v7:$support" @@ -70,9 +67,9 @@ dependencies { implementation "com.android.support:customtabs:$support" // Firebase - implementation "com.google.firebase:firebase-messaging:$playServices" - implementation "com.google.firebase:firebase-database:$playServices" - implementation "com.google.firebase:firebase-core:$playServices" + implementation "com.google.firebase:firebase-messaging:17.3.4" + implementation "com.google.firebase:firebase-database:16.0.4" + implementation "com.google.firebase:firebase-core:16.0.4" // Crashlytics only for release builds releaseImplementation('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') { diff --git a/Droidcon-Boston/build.gradle b/Droidcon-Boston/build.gradle index 46c1b05..b556fe4 100644 --- a/Droidcon-Boston/build.gradle +++ b/Droidcon-Boston/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.2.30' + ext.kotlin_version = '1.3.0' repositories { google() jcenter() @@ -10,14 +10,14 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'com.android.tools.build:gradle:3.3.0-beta02' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files - classpath 'com.google.gms:google-services:3.2.0' + classpath 'com.google.gms:google-services:4.0.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'io.fabric.tools:gradle:1.25.1' + classpath 'io.fabric.tools:gradle:1.25.4' } } diff --git a/Droidcon-Boston/gradle/wrapper/gradle-wrapper.properties b/Droidcon-Boston/gradle/wrapper/gradle-wrapper.properties index 52b6e6b..2c508e6 100644 --- a/Droidcon-Boston/gradle/wrapper/gradle-wrapper.properties +++ b/Droidcon-Boston/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip From 342525eb1b06326deebcc8f178dc5091f55c32ea Mon Sep 17 00:00:00 2001 From: Nishant Srivastava Date: Sat, 3 Nov 2018 02:26:17 +0100 Subject: [PATCH 003/173] =?UTF-8?q?=F0=9F=A4=96=20android=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../droidcon_boston/data/UserAgendaRepo.kt | 2 +- .../utils/DividerItemDecoration.kt | 12 ++++---- .../utils/NotificationUtils.kt | 8 ++--- .../droidcon_boston/views/MainActivity.kt | 29 ++++++++++++------- .../views/agenda/AgendaDayFragment.kt | 10 +++---- .../views/detail/AgendaDetailFragment.kt | 16 +++------- 6 files changed, 35 insertions(+), 42 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt index 66ebe5f..b219fc0 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt @@ -12,7 +12,7 @@ class UserAgendaRepo private constructor(context: Context) { private val savedSessionIds = HashSet() init { - savedSessionIds.addAll(sharedPrefs.getStringSet(sessionIdsKey, HashSet())) + savedSessionIds += sharedPrefs.getStringSet(sessionIdsKey, HashSet()) } fun isSessionBookmarked(sessionId : String) : Boolean { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt index 89c6c8a..0207e57 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt @@ -59,15 +59,15 @@ class DividerItemDecoration(context: Context, orientation: Int) : RecyclerView.I } } - override fun getItemOffsets(outRect: Rect?, view: View?, parent: RecyclerView?, state: State?) { + override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: State) { if (orientationValue == VERTICAL_LIST) { - outRect?.set(0, 0, 0, divider!!.intrinsicHeight) - } else { - outRect?.set(0, 0, divider!!.intrinsicWidth, 0) - } + outRect.set(0, 0, 0, divider!!.intrinsicHeight) + } else { + outRect.set(0, 0, divider!!.intrinsicWidth, 0) + } } - override fun onDraw(c: Canvas?, parent: RecyclerView?, state: State?) { + override fun onDraw(c: Canvas, parent: RecyclerView, state: State) { if (orientationValue == VERTICAL_LIST) { drawVertical(c, parent) } else { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt index 252e466..730fd58 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt @@ -1,11 +1,7 @@ package com.mentalmachines.droidcon_boston.utils import android.annotation.TargetApi -import android.app.AlarmManager -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.app.PendingIntent +import android.app.* import android.content.ComponentName import android.content.Context import android.content.ContextWrapper @@ -91,7 +87,7 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { override fun onDataChange(dataSnapshot: DataSnapshot) { var hasBookmarkedEvents = false for (roomSnapshot in dataSnapshot.children) { - val eventId = roomSnapshot.key + val eventId = roomSnapshot.key ?: "" val scheduleEvent = roomSnapshot.getValue(FirebaseDatabase.ScheduleEvent::class.java) scheduleEvent?.let { if (userRepo.isSessionBookmarked(eventId) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index 7098c77..fffedf8 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -21,9 +21,7 @@ import com.mentalmachines.droidcon_boston.views.detail.AgendaDetailFragment import com.mentalmachines.droidcon_boston.views.social.SocialFragment import com.mentalmachines.droidcon_boston.views.speaker.SpeakerFragment import com.mentalmachines.droidcon_boston.views.volunteer.VolunteerFragment -import kotlinx.android.synthetic.main.main_activity.drawer_layout -import kotlinx.android.synthetic.main.main_activity.navView -import kotlinx.android.synthetic.main.main_activity.toolbar +import kotlinx.android.synthetic.main.main_activity.* class MainActivity : AppCompatActivity() { @@ -141,9 +139,9 @@ class MainActivity : AppCompatActivity() { when (item.itemId) { // Respond to the action bar's Up/Home button - android.R.id.home -> if (fragmentManager.backStackEntryCount > 0) { - fragmentManager.popBackStack() - } else if (fragmentManager.backStackEntryCount == 1) { + android.R.id.home -> if (supportFragmentManager.backStackEntryCount > 0) { + supportFragmentManager.popBackStack() + } else if (supportFragmentManager?.backStackEntryCount == 1) { // to avoid looping below on initScreen super.onBackPressed() finish() @@ -214,7 +212,13 @@ class MainActivity : AppCompatActivity() { resources.getString(R.string.str_volunteers) -> fragment = VolunteerFragment() } // Add fragment with tag - supportFragmentManager.beginTransaction().replace(R.id.fragment_container, fragment, title).commit() + fragment?.let{ + supportFragmentManager?.beginTransaction() + // replace in container + ?.replace(R.id.fragment_container, it, title) + // commit fragment transaction + ?.commit() + } } else { // For Agenda and My Schedule Screen, which add more fragments to backstack. @@ -226,13 +230,16 @@ class MainActivity : AppCompatActivity() { popUntilLastFragment() } - supportFragmentManager.beginTransaction() + val fragmentInContainer = supportFragmentManager?.findFragmentById(R.id.fragment_container) + fragmentInContainer?.let{ + supportFragmentManager?.beginTransaction() // detach the fragment that is currently visible - .detach(supportFragmentManager.findFragmentById(R.id.fragment_container)) + ?.detach(it) // attach the fragment found as per the tag - .attach(fragment) + ?.attach(it) // commit fragment transaction - .commit() + ?.commit() + } } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index 0d8ff5c..d57a8b0 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -16,11 +16,9 @@ import com.google.firebase.database.DatabaseError import com.google.firebase.database.ValueEventListener import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.data.FirebaseDatabase.ScheduleEvent -import com.mentalmachines.droidcon_boston.data.Schedule import com.mentalmachines.droidcon_boston.data.Schedule.ScheduleRow import com.mentalmachines.droidcon_boston.data.UserAgendaRepo import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper -import com.mentalmachines.droidcon_boston.utils.ServiceLocator.Companion.gson import com.mentalmachines.droidcon_boston.utils.isNullorEmpty import com.mentalmachines.droidcon_boston.views.detail.AgendaDetailFragment import eu.davidea.flexibleadapter.FlexibleAdapter @@ -56,7 +54,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { android.R.id.home -> { val fragmentManager = activity?.supportFragmentManager if (fragmentManager?.backStackEntryCount!! > 0) { - fragmentManager.popBackStack() + fragmentManager?.popBackStack() } } } @@ -101,14 +99,14 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { } fun updateList() { - agendaRecyler.adapter.notifyDataSetChanged() + agendaRecyler.adapter?.notifyDataSetChanged() } val dataListener: ValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { val rows = ArrayList() for (roomSnapshot in dataSnapshot.children) { - val key = roomSnapshot.key + val key = roomSnapshot.key ?: "" val data = roomSnapshot.getValue(ScheduleEvent::class.java) Log.d(TAG, "Event: $data") if (data != null) { @@ -171,7 +169,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { val i = Intent(Intent.ACTION_VIEW) i.data = Uri.parse(url) val packageManager = activity?.packageManager - if (i.resolveActivity(packageManager) != null) { + if (packageManager !=null && i.resolveActivity(packageManager) != null) { startActivity(i) } return false diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt index 7fca566..d2903a9 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt @@ -30,15 +30,7 @@ import com.mentalmachines.droidcon_boston.utils.ServiceLocator.Companion.gson import com.mentalmachines.droidcon_boston.utils.getHtmlFormattedSpanned import com.mentalmachines.droidcon_boston.views.MainActivity import com.mentalmachines.droidcon_boston.views.transform.CircleTransform -import kotlinx.android.synthetic.main.agenda_detail_fragment.agendaDetailView -import kotlinx.android.synthetic.main.agenda_detail_fragment.fab_agenda_detail_bookmark -import kotlinx.android.synthetic.main.agenda_detail_fragment.tv_agenda_detail_description -import kotlinx.android.synthetic.main.agenda_detail_fragment.tv_agenda_detail_room -import kotlinx.android.synthetic.main.agenda_detail_fragment.tv_agenda_detail_speaker_name -import kotlinx.android.synthetic.main.agenda_detail_fragment.tv_agenda_detail_speaker_title -import kotlinx.android.synthetic.main.agenda_detail_fragment.tv_agenda_detail_time -import kotlinx.android.synthetic.main.agenda_detail_fragment.tv_agenda_detail_title -import kotlinx.android.synthetic.main.agenda_detail_fragment.v_agenda_detail_speaker_divider +import kotlinx.android.synthetic.main.agenda_detail_fragment.* class AgendaDetailFragment : Fragment() { @@ -241,9 +233,9 @@ class AgendaDetailFragment : Fragment() { agendaDetailFragment.arguments = arguments supportFragmentManager.beginTransaction() - ?.add(R.id.fragment_container, agendaDetailFragment) - ?.addToBackStack(null) - ?.commit() + .add(R.id.fragment_container, agendaDetailFragment) + .addToBackStack(null) + .commit() } } } From 3dbf95ff5d7c4fc09a808e399a88c41d5c5a0fa0 Mon Sep 17 00:00:00 2001 From: Nishant Srivastava Date: Sat, 3 Nov 2018 02:35:25 +0100 Subject: [PATCH 004/173] =?UTF-8?q?=F0=9F=8E=A8=20structure/format:=20code?= =?UTF-8?q?base?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/src/main/AndroidManifest.xml | 2 +- .../droidcon_boston/data/FirebaseDatabase.kt | 83 +++++++++---------- .../droidcon_boston/data/Schedule.kt | 31 ++++--- .../droidcon_boston/data/UserAgendaRepo.kt | 7 +- .../firebase/DbFirebaseMessagingService.kt | 4 +- .../firebase/FirebaseHelper.kt | 2 +- .../droidcon_boston/receivers/BootReceiver.kt | 2 +- .../receivers/NotificationPublisher.kt | 3 +- .../utils/DividerItemDecoration.kt | 24 +++--- .../utils/ExtensionFunctions.kt | 6 +- .../utils/NotificationUtils.kt | 74 ++++++++++------- .../utils/RVItemClickListener.kt | 17 ++-- .../droidcon_boston/utils/SingletonHolder.kt | 3 +- .../droidcon_boston/views/AboutFragment.kt | 8 +- .../droidcon_boston/views/CocFragment.kt | 6 +- .../droidcon_boston/views/FAQFragment.kt | 18 ++-- .../droidcon_boston/views/MainActivity.kt | 33 ++++---- .../droidcon_boston/views/SplashActivity.kt | 6 +- .../views/agenda/AgendaDayFragment.kt | 22 +++-- .../views/agenda/AgendaDayPagerAdapter.kt | 8 +- .../views/agenda/AgendaFragment.kt | 11 ++- .../agenda/FixedFragmentStatePagerAdapter.kt | 7 +- .../views/agenda/ScheduleAdapterItem.kt | 38 ++++----- .../views/agenda/ScheduleAdapterItemHeader.kt | 15 ++-- .../views/detail/AgendaDetailFragment.kt | 61 +++++++------- .../views/detail/SpeakerDetailFragment.kt | 33 ++++---- .../views/faq/FaqAdapterItem.kt | 15 ++-- .../views/faq/FaqAdapterItemHeader.kt | 15 ++-- .../views/social/RVSocialListAdapter.kt | 5 +- .../views/social/SocialFragment.kt | 41 +++++---- .../views/speaker/SpeakerAdapterItem.kt | 21 ++--- .../views/speaker/SpeakerFragment.kt | 12 +-- .../views/transform/CircleTransform.kt | 5 +- .../views/volunteer/VolunteerAdapterItem.kt | 22 ++--- .../views/volunteer/VolunteerFragment.kt | 12 ++- .../src/main/res/drawable/bg_social_btn.xml | 6 +- .../circular_textview_accent_background.xml | 2 +- .../app/src/main/res/drawable/ic_aboutus.xml | 10 +-- .../app/src/main/res/drawable/ic_agenda.xml | 10 +-- .../app/src/main/res/drawable/ic_coc.xml | 10 +-- .../app/src/main/res/drawable/ic_faq.xml | 10 +-- .../src/main/res/drawable/ic_my_schedule.xml | 10 +-- .../app/src/main/res/drawable/ic_social.xml | 10 +-- .../app/src/main/res/drawable/ic_speakers.xml | 10 +-- .../app/src/main/res/drawable/ic_star.xml | 10 +-- .../src/main/res/drawable/ic_volunteers.xml | 10 +-- .../app/src/main/res/drawable/social_back.xml | 5 +- .../src/main/res/drawable/social_press.xml | 5 +- .../src/main/res/layout/about_fragment.xml | 18 ++-- .../main/res/layout/agenda_day_fragment.xml | 12 ++- .../res/layout/agenda_detail_fragment.xml | 14 ++-- .../src/main/res/layout/agenda_fragment.xml | 4 +- .../app/src/main/res/layout/coc_fragment.xml | 4 +- .../app/src/main/res/layout/empty_view.xml | 11 ++- .../app/src/main/res/layout/faq_fragment.xml | 7 +- .../app/src/main/res/layout/faq_header.xml | 7 +- .../app/src/main/res/layout/faq_item.xml | 22 ++--- .../app/src/main/res/layout/nav_header.xml | 8 +- .../app/src/main/res/layout/schedule_item.xml | 81 +++++++++--------- .../main/res/layout/schedule_item_header.xml | 35 ++++---- .../src/main/res/layout/social_fragment.xml | 4 +- .../src/main/res/layout/social_list_item.xml | 10 +-- .../res/layout/speaker_detail_fragment.xml | 22 ++--- .../app/src/main/res/layout/speaker_item.xml | 12 +-- .../src/main/res/layout/splash_activity.xml | 11 ++- .../src/main/res/layout/volunteer_item.xml | 12 +-- .../res/mipmap-anydpi-v26/ic_launcher.xml | 4 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 4 +- .../droidcon_boston/data/ScheduleTest.kt | 7 +- 69 files changed, 563 insertions(+), 526 deletions(-) diff --git a/Droidcon-Boston/app/src/main/AndroidManifest.xml b/Droidcon-Boston/app/src/main/AndroidManifest.xml index eec4108..ad71820 100644 --- a/Droidcon-Boston/app/src/main/AndroidManifest.xml +++ b/Droidcon-Boston/app/src/main/AndroidManifest.xml @@ -29,8 +29,8 @@ diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt index aa62750..3b09af9 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt @@ -14,34 +14,37 @@ import org.threeten.bp.format.DateTimeFormatter open class FirebaseDatabase { - data class ScheduleEvent( - private val SESSION_REMINDER_MINUTES_BEFORE: Long = 10, - - var primarySpeakerName: String = "", - var startTime: String = "", - var name: String = "", - - var speakerNames: HashMap = HashMap(0), - var speakerNameToPhotoUrl: HashMap = HashMap(0), - var speakerNameToOrg: HashMap = HashMap(0), - var roomNames: HashMap = HashMap(0), - var speakerIds: HashMap = HashMap(0), - var roomIds: HashMap = HashMap(0), - var description: String = "", - var photo: HashMap = HashMap(0), - var endTime: String = "", - var trackSortOrder: Int = 0) { - - val conferenceTZ = ZoneId.of( "America/New_York" ) + data class ScheduleEvent(private val SESSION_REMINDER_MINUTES_BEFORE: Long = 10, + + var primarySpeakerName: String = "", + var startTime: String = "", + var name: String = "", + + var speakerNames: HashMap = HashMap(0), + var speakerNameToPhotoUrl: HashMap = HashMap(0), + var speakerNameToOrg: HashMap = HashMap(0), + var roomNames: HashMap = HashMap(0), + var speakerIds: HashMap = HashMap(0), + var roomIds: HashMap = HashMap(0), + var description: String = "", + var photo: HashMap = HashMap(0), + var endTime: String = "", + var trackSortOrder: Int = 0) { + + val conferenceTZ = ZoneId.of("America/New_York") fun getLocalStartTime(): LocalDateTime { - return ZonedDateTime.parse(startTime).withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime() + return ZonedDateTime.parse(startTime).withZoneSameInstant(ZoneId.systemDefault()) + .toLocalDateTime() } fun scheduleNotification(context: Context, eventId: String, sessionDetail: ScheduleRow) { - NotificationUtils(context).scheduleNotificationAlarm(getLocalStartTime().minusMinutes(SESSION_REMINDER_MINUTES_BEFORE), - eventId, context.getString(R.string.str_session_start_soon, name), description.getHtmlFormattedSpanned().toString(), - ServiceLocator.gson.toJson(sessionDetail, ScheduleRow::class.java)) + NotificationUtils(context).scheduleNotificationAlarm(getLocalStartTime().minusMinutes( + SESSION_REMINDER_MINUTES_BEFORE), + eventId, + context.getString(R.string.str_session_start_soon, name), + description.getHtmlFormattedSpanned().toString(), + ServiceLocator.gson.toJson(sessionDetail, ScheduleRow::class.java)) } fun toScheduleRow(scheduleId: String): ScheduleRow { @@ -81,13 +84,12 @@ open class FirebaseDatabase { } } - data class EventSpeaker( - val pictureUrl: String = "", - val socialProfiles: HashMap? = HashMap(0), - var bio: String = "", - var title: String = "", - var org: String = "", - var name: String = "") { + data class EventSpeaker(val pictureUrl: String = "", + val socialProfiles: HashMap? = HashMap(0), + var bio: String = "", + var title: String = "", + var org: String = "", + var name: String = "") { fun toScheduleDetail(listRow: ScheduleRow): ScheduleDetail { val detail = ScheduleDetail(listRow) @@ -103,21 +105,18 @@ open class FirebaseDatabase { } } - data class VolunteerEvent( - val twitter: String = "", - val pictureUrl: String = "", - var position: String = "", - var firstName: String = "", - var lastName: String = "") + data class VolunteerEvent(val twitter: String = "", + val pictureUrl: String = "", + var position: String = "", + var firstName: String = "", + var lastName: String = "") class FaqEvent { - data class Answer( - var answer: String = "", - var photoLink: String = "", - var mapLink: String = "", - var otherLink: String = "" - ) + data class Answer(var answer: String = "", + var photoLink: String = "", + var mapLink: String = "", + var otherLink: String = "") var answers: List = emptyList() var question: String = "" diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt index 08df8eb..1f3ce3a 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt @@ -6,22 +6,21 @@ package com.mentalmachines.droidcon_boston.data */ class Schedule { - data class ScheduleRow( - var primarySpeakerName: String = "", - var id: String = "", - var startTime: String = "", - var talkTitle: String = "", - var speakerCount: Int = 0, - var talkDescription: String = "", - var speakerNames: List = emptyList(), - var speakerNameToOrgName: HashMap = HashMap(0), - var utcStartTimeString: String = "", - var endTime: String = "", - var room: String = "", - var date: String = "", - var trackSortOrder: Int = 0, - var photoUrlMap: HashMap = HashMap(0), - var isOver: Boolean = false) { + data class ScheduleRow(var primarySpeakerName: String = "", + var id: String = "", + var startTime: String = "", + var talkTitle: String = "", + var speakerCount: Int = 0, + var talkDescription: String = "", + var speakerNames: List = emptyList(), + var speakerNameToOrgName: HashMap = HashMap(0), + var utcStartTimeString: String = "", + var endTime: String = "", + var room: String = "", + var date: String = "", + var trackSortOrder: Int = 0, + var photoUrlMap: HashMap = HashMap(0), + var isOver: Boolean = false) { fun hasSpeaker(): Boolean = speakerNames.isNotEmpty() diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt index b219fc0..5a3c6ad 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt @@ -8,18 +8,19 @@ import com.mentalmachines.droidcon_boston.utils.SingletonHolder class UserAgendaRepo private constructor(context: Context) { private val prefsKey = "UserAgenda" private val sessionIdsKey = "savedSessionsIds" - private val sharedPrefs : SharedPreferences = context.getSharedPreferences(prefsKey, MODE_PRIVATE) + private val sharedPrefs: SharedPreferences = + context.getSharedPreferences(prefsKey, MODE_PRIVATE) private val savedSessionIds = HashSet() init { savedSessionIds += sharedPrefs.getStringSet(sessionIdsKey, HashSet()) } - fun isSessionBookmarked(sessionId : String) : Boolean { + fun isSessionBookmarked(sessionId: String): Boolean { return savedSessionIds.contains(sessionId) } - fun bookmarkSession(sessionId : String, flag : Boolean) { + fun bookmarkSession(sessionId: String, flag: Boolean) { if (flag) { savedSessionIds.add(sessionId) } else { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt index 4c90685..c43f0f5 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt @@ -32,7 +32,9 @@ class DbFirebaseMessagingService : FirebaseMessagingService() { // Show the notification here val notificationUtils = NotificationUtils(this) - notificationUtils.sendAndroidChannelNotification(getString(R.string.conference_name), bodyStr!!, 101) + notificationUtils.sendAndroidChannelNotification(getString(R.string.conference_name), + bodyStr!!, + 101) } } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/FirebaseHelper.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/FirebaseHelper.kt index 4440cbd..39fd91a 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/FirebaseHelper.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/FirebaseHelper.kt @@ -13,7 +13,7 @@ class FirebaseHelper private constructor() { val aboutDatabase: DatabaseReference val faqDatabase: DatabaseReference val cocDatabase: DatabaseReference - val volunteerDatabase : DatabaseReference + val volunteerDatabase: DatabaseReference init { this.database = FirebaseDatabase.getInstance() diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/BootReceiver.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/BootReceiver.kt index 17d1fd8..c4fc75c 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/BootReceiver.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/BootReceiver.kt @@ -1,8 +1,8 @@ package com.mentalmachines.droidcon_boston.receivers -import android.content.Intent import android.content.BroadcastReceiver import android.content.Context +import android.content.Intent import com.mentalmachines.droidcon_boston.utils.NotificationUtils diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/NotificationPublisher.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/NotificationPublisher.kt index b09e66c..86fbb63 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/NotificationPublisher.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/NotificationPublisher.kt @@ -9,7 +9,8 @@ import android.content.Intent class NotificationPublisher : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val notificationManager = + context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notification = intent.getParcelableExtra(NOTIFICATION) val id = intent.getIntExtra(NOTIFICATION_ID, 0) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt index 0207e57..06cb613 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt @@ -30,11 +30,9 @@ class DividerItemDecoration(context: Context, orientation: Int) : RecyclerView.I val childCount = parent.childCount for (i in 0 until childCount) { val child = parent.getChildAt(i) - val params = child - .layoutParams as RecyclerView.LayoutParams - @Suppress("DEPRECATION") - val left = child.right + params.rightMargin + - Math.round(ViewCompat.getTranslationX(child)) + val params = child.layoutParams as RecyclerView.LayoutParams + @Suppress("DEPRECATION") val left = + child.right + params.rightMargin + Math.round(ViewCompat.getTranslationX(child)) val right = left + divider!!.intrinsicHeight divider.setBounds(left, top, right, bottom) divider.draw(c!!) @@ -48,11 +46,9 @@ class DividerItemDecoration(context: Context, orientation: Int) : RecyclerView.I val childCount = parent.childCount for (i in 0 until childCount) { val child = parent.getChildAt(i) - val params = child - .layoutParams as RecyclerView.LayoutParams - @Suppress("DEPRECATION") - val top = child.bottom + params.bottomMargin + - Math.round(ViewCompat.getTranslationY(child)) + val params = child.layoutParams as RecyclerView.LayoutParams + @Suppress("DEPRECATION") val top = + child.bottom + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child)) val bottom = top + divider!!.intrinsicHeight divider.setBounds(left, top, right, bottom) divider.draw(c!!) @@ -61,10 +57,10 @@ class DividerItemDecoration(context: Context, orientation: Int) : RecyclerView.I override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: State) { if (orientationValue == VERTICAL_LIST) { - outRect.set(0, 0, 0, divider!!.intrinsicHeight) - } else { - outRect.set(0, 0, divider!!.intrinsicWidth, 0) - } + outRect.set(0, 0, 0, divider!!.intrinsicHeight) + } else { + outRect.set(0, 0, divider!!.intrinsicWidth, 0) + } } override fun onDraw(c: Canvas, parent: RecyclerView, state: State) { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt index ac7bf59..7c4438e 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt @@ -18,8 +18,7 @@ fun String.getHtmlFormattedSpanned(): Spanned { return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { Html.fromHtml(this, Html.FROM_HTML_MODE_COMPACT) } else { - @Suppress("DEPRECATION") - Html.fromHtml(this) + @Suppress("DEPRECATION") Html.fromHtml(this) } } @@ -27,7 +26,6 @@ fun String.getHtmlFormattedSpanned(): Spanned { fun Context.loadUriInCustomTab(uriString: String) { val data = Uri.parse(uriString) val customTabsIntent = CustomTabsIntent.Builder() - .setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary)) - .build() + .setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary)).build() customTabsIntent.launchUrl(this, data) } \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt index 730fd58..210bfb7 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt @@ -38,7 +38,8 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // create android channel val androidChannel = NotificationChannel(ANDROID_CHANNEL_ID, - ANDROID_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT) + ANDROID_CHANNEL_NAME, + NotificationManager.IMPORTANCE_DEFAULT) // Sets whether notifications posted to this channel should display notification lights androidChannel.enableLights(true) // Sets whether notification posted to this channel should vibrate. @@ -57,18 +58,17 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { return getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager } - private fun sendChannelNotification(title: String, body: String, notificationId: Int, channelId: String) { + private fun sendChannelNotification(title: String, + body: String, + notificationId: Int, + channelId: String) { val resultIntent = Intent(this, MainActivity::class.java) - val pi = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent - .FLAG_UPDATE_CURRENT) - - val builder = NotificationCompat.Builder(applicationContext, - channelId) - .setContentTitle(title) - .setContentText(body) - .setTicker(getString(R.string.conference_name)) - .setSmallIcon(android.R.drawable.stat_notify_more) - .setAutoCancel(true) + val pi = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT) + + val builder = + NotificationCompat.Builder(applicationContext, channelId).setContentTitle(title) + .setContentText(body).setTicker(getString(R.string.conference_name)) + .setSmallIcon(android.R.drawable.stat_notify_more).setAutoCancel(true) // for notification click action, also required on Gingerbread and below .setContentIntent(pi) @@ -88,11 +88,14 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { var hasBookmarkedEvents = false for (roomSnapshot in dataSnapshot.children) { val eventId = roomSnapshot.key ?: "" - val scheduleEvent = roomSnapshot.getValue(FirebaseDatabase.ScheduleEvent::class.java) + val scheduleEvent = + roomSnapshot.getValue(FirebaseDatabase.ScheduleEvent::class.java) scheduleEvent?.let { - if (userRepo.isSessionBookmarked(eventId) - && scheduleEvent.getLocalStartTime().isAfter(LocalDateTime.now())) { - scheduleEvent.scheduleNotification(context, eventId, scheduleEvent.toScheduleRow(eventId)) + if (userRepo.isSessionBookmarked(eventId) && scheduleEvent.getLocalStartTime().isAfter( + LocalDateTime.now())) { + scheduleEvent.scheduleNotification(context, + eventId, + scheduleEvent.toScheduleRow(eventId)) hasBookmarkedEvents = true } } @@ -110,9 +113,14 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { }) } - fun scheduleNotificationAlarm(alarmTime: LocalDateTime, sessionId: String, title: String, body: String, sessionDetail: String) { + fun scheduleNotificationAlarm(alarmTime: LocalDateTime, + sessionId: String, + title: String, + body: String, + sessionDetail: String) { if (alarmTime.isAfter(LocalDateTime.now())) { - val pendingIntent = getAgendaSessionNotificationPendingIntent(sessionId, title, body, sessionDetail) + val pendingIntent = + getAgendaSessionNotificationPendingIntent(sessionId, title, body, sessionDetail) val utcInMillis = alarmTime.atZone(ZoneId.systemDefault()).toEpochSecond() * 1000 val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmManager.set(AlarmManager.RTC_WAKEUP, utcInMillis, pendingIntent) @@ -131,24 +139,25 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { val pm = context.packageManager pm.setComponentEnabledSetting(receiver, - if (enabled) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, - PackageManager.DONT_KILL_APP) + if (enabled) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP) } - private fun getAgendaSessionNotificationPendingIntent(sessionId: String, title: String = "", body: String = "", sessionDetail: String = ""): PendingIntent { - val builder = NotificationCompat.Builder(this, ANDROID_CHANNEL_ID) - .setContentText(title) - .setStyle(NotificationCompat.BigTextStyle() - .bigText(body) - .setBigContentTitle(title)) - .setSmallIcon(R.drawable.ic_notification_session_start) - .setAutoCancel(true) + private fun getAgendaSessionNotificationPendingIntent(sessionId: String, + title: String = "", + body: String = "", + sessionDetail: String = ""): PendingIntent { + val builder = NotificationCompat.Builder(this, ANDROID_CHANNEL_ID).setContentText(title) + .setStyle(NotificationCompat.BigTextStyle().bigText(body).setBigContentTitle(title)) + .setSmallIcon(R.drawable.ic_notification_session_start).setAutoCancel(true) val notificationId = sessionId.hashCode() if (!TextUtils.isEmpty(sessionDetail)) { val sessionIntent = MainActivity.getSessionDetailIntent(this, sessionId, sessionDetail) - val contentIntent = PendingIntent.getActivity(this, notificationId, - sessionIntent, PendingIntent.FLAG_UPDATE_CURRENT) + val contentIntent = PendingIntent.getActivity(this, + notificationId, + sessionIntent, + PendingIntent.FLAG_UPDATE_CURRENT) builder.setContentIntent(contentIntent) } @@ -158,7 +167,10 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { putExtra(NotificationPublisher.SESSION_ID, sessionId) putExtra(NotificationPublisher.NOTIFICATION, builder.build()) } - return PendingIntent.getBroadcast(this, notificationId, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT) + return PendingIntent.getBroadcast(this, + notificationId, + notificationIntent, + PendingIntent.FLAG_UPDATE_CURRENT) } companion object { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt index ac698ff..defd5a5 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt @@ -6,13 +6,16 @@ import android.view.GestureDetector import android.view.MotionEvent import android.view.View -open class RVItemClickListener(context: Context, private val itemClickListener: OnItemClickListener?) : RecyclerView.OnItemTouchListener { - - private var gestureDetector: GestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { - override fun onSingleTapUp(e: MotionEvent): Boolean { - return true - } - }) +open class RVItemClickListener(context: Context, + private val itemClickListener: OnItemClickListener?) : + RecyclerView.OnItemTouchListener { + + private var gestureDetector: GestureDetector = + GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { + override fun onSingleTapUp(e: MotionEvent): Boolean { + return true + } + }) interface OnItemClickListener { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/SingletonHolder.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/SingletonHolder.kt index 8054715..0104eac 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/SingletonHolder.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/SingletonHolder.kt @@ -4,7 +4,8 @@ package com.mentalmachines.droidcon_boston.utils // Kotlin singletons really should have a constructor :-P open class SingletonHolder(creator: (A) -> T) { private var creator: ((A) -> T)? = creator - @Volatile private var instance: T? = null + @Volatile + private var instance: T? = null fun getInstance(arg: A): T { val i = instance diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt index 018d749..b8f6d96 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt @@ -13,13 +13,14 @@ import com.google.firebase.database.ValueEventListener import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper import com.mentalmachines.droidcon_boston.utils.getHtmlFormattedSpanned -import kotlinx.android.synthetic.main.about_fragment.tv_about_description +import kotlinx.android.synthetic.main.about_fragment.* class AboutFragment : Fragment() { private val firebaseHelper = FirebaseHelper.instance - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.about_fragment, container, false) } @@ -37,7 +38,8 @@ class AboutFragment : Fragment() { val dataListener: ValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { - tv_about_description.text = dataSnapshot.getValue(String::class.java)?.getHtmlFormattedSpanned() + tv_about_description.text = + dataSnapshot.getValue(String::class.java)?.getHtmlFormattedSpanned() tv_about_description.movementMethod = LinkMovementMethod.getInstance() } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt index c889603..00402b5 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt @@ -14,13 +14,15 @@ import com.google.firebase.database.ValueEventListener import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper import com.mentalmachines.droidcon_boston.utils.getHtmlFormattedSpanned -import kotlinx.android.synthetic.main.coc_fragment.tv_coc +import kotlinx.android.synthetic.main.coc_fragment.* class CocFragment : Fragment() { private val firebaseHelper = FirebaseHelper.instance - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.coc_fragment, container, false) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt index c7720a4..338ca1f 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt @@ -19,9 +19,8 @@ import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper import com.mentalmachines.droidcon_boston.views.faq.FaqAdapterItem import com.mentalmachines.droidcon_boston.views.faq.FaqAdapterItemHeader import eu.davidea.flexibleadapter.FlexibleAdapter -import kotlinx.android.synthetic.main.faq_fragment.faq_recycler -import java.util.ArrayList -import java.util.HashMap +import kotlinx.android.synthetic.main.faq_fragment.* +import java.util.* class FAQFragment : Fragment(), FlexibleAdapter.OnItemClickListener { @@ -30,7 +29,9 @@ class FAQFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private lateinit var headerAdapter: FlexibleAdapter - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(layout.faq_fragment, container, false) } @@ -75,7 +76,8 @@ class FAQFragment : Fragment(), FlexibleAdapter.OnItemClickListener { val items = ArrayList(faqs.size) faqs.forEach { faq -> faq.answers.forEach { answer -> - val header: FaqAdapterItemHeader = questionHeaders[faq.question] ?: FaqAdapterItemHeader(faq.question) + val header: FaqAdapterItemHeader = + questionHeaders[faq.question] ?: FaqAdapterItemHeader(faq.question) questionHeaders[faq.question] = header val item = FaqAdapterItem(answer, header) @@ -87,8 +89,7 @@ class FAQFragment : Fragment(), FlexibleAdapter.OnItemClickListener { headerAdapter = FlexibleAdapter(items) headerAdapter.addListener(this) faq_recycler.adapter = headerAdapter - headerAdapter.expandItemsAtStartUp() - .setDisplayHeadersAtStartUp(true) + headerAdapter.expandItemsAtStartUp().setDisplayHeadersAtStartUp(true) } override fun onItemClick(view: View, position: Int): Boolean { @@ -96,7 +97,8 @@ class FAQFragment : Fragment(), FlexibleAdapter.OnItemClickListener { val item = headerAdapter.getItem(position) val itemData = item!!.itemData - val url = if (!TextUtils.isEmpty(itemData.otherLink)) itemData.otherLink else itemData.mapLink + val url = + if (!TextUtils.isEmpty(itemData.otherLink)) itemData.otherLink else itemData.mapLink val intent = Intent(Intent.ACTION_VIEW) intent.data = Uri.parse(url) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index fffedf8..f86f13a 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -43,7 +43,7 @@ class MainActivity : AppCompatActivity() { val sessionDetails = initialIntent.extras?.getString(EXTRA_SESSION_DETAILS) if (!TextUtils.isEmpty(sessionDetails)) { AgendaDetailFragment.addDetailFragmentToStack(supportFragmentManager, - ServiceLocator.gson.fromJson(sessionDetails, ScheduleRow::class.java)) + ServiceLocator.gson.fromJson(sessionDetails, ScheduleRow::class.java)) } else { navView.setCheckedItem(id.nav_agenda) } @@ -84,7 +84,8 @@ class MainActivity : AppCompatActivity() { } private fun checkNavMenuItem(title: String) { - processMenuItems({ item -> item.title == title }, { item -> item.setChecked(true).isChecked }) + processMenuItems({ item -> item.title == title }, + { item -> item.setChecked(true).isChecked }) } private fun isNavItemChecked(title: String): Boolean { @@ -128,8 +129,10 @@ class MainActivity : AppCompatActivity() { setSupportActionBar(toolbar) - actionBarDrawerToggle = ActionBarDrawerToggle(this, drawer_layout, - R.string.drawer_open, R.string.drawer_close) + actionBarDrawerToggle = ActionBarDrawerToggle(this, + drawer_layout, + R.string.drawer_open, + R.string.drawer_close) drawer_layout.addDrawerListener(actionBarDrawerToggle) navView.setNavigationItemSelectedListener { item -> @@ -138,7 +141,7 @@ class MainActivity : AppCompatActivity() { drawer_layout.closeDrawers() when (item.itemId) { - // Respond to the action bar's Up/Home button + // Respond to the action bar's Up/Home button android.R.id.home -> if (supportFragmentManager.backStackEntryCount > 0) { supportFragmentManager.popBackStack() } else if (supportFragmentManager?.backStackEntryCount == 1) { @@ -203,7 +206,8 @@ class MainActivity : AppCompatActivity() { // Initialize the fragment based on tag when (title) { resources.getString(R.string.str_agenda) -> fragment = AgendaFragment.newInstance() - resources.getString(R.string.str_my_schedule) -> fragment = AgendaFragment.newInstanceMySchedule() + resources.getString(R.string.str_my_schedule) -> fragment = + AgendaFragment.newInstanceMySchedule() resources.getString(R.string.str_faq) -> fragment = FAQFragment() resources.getString(R.string.str_social) -> fragment = SocialFragment() resources.getString(R.string.str_coc) -> fragment = CocFragment() @@ -212,7 +216,7 @@ class MainActivity : AppCompatActivity() { resources.getString(R.string.str_volunteers) -> fragment = VolunteerFragment() } // Add fragment with tag - fragment?.let{ + fragment?.let { supportFragmentManager?.beginTransaction() // replace in container ?.replace(R.id.fragment_container, it, title) @@ -224,14 +228,13 @@ class MainActivity : AppCompatActivity() { // For Agenda and My Schedule Screen, which add more fragments to backstack. // Remove all fragment except the last one when navigating via the nav drawer. when (title) { - resources.getString(R.string.str_agenda) -> - popUntilLastFragment() - resources.getString(R.string.str_my_schedule) -> - popUntilLastFragment() + resources.getString(R.string.str_agenda) -> popUntilLastFragment() + resources.getString(R.string.str_my_schedule) -> popUntilLastFragment() } - val fragmentInContainer = supportFragmentManager?.findFragmentById(R.id.fragment_container) - fragmentInContainer?.let{ + val fragmentInContainer = + supportFragmentManager?.findFragmentById(R.id.fragment_container) + fragmentInContainer?.let { supportFragmentManager?.beginTransaction() // detach the fragment that is currently visible ?.detach(it) @@ -259,7 +262,9 @@ class MainActivity : AppCompatActivity() { private const val EXTRA_SESSIONID = "MainActivity.EXTRA_SESSIONID" private const val EXTRA_SESSION_DETAILS = "MainActivity.EXTRA_SESSION_DETAILS" - fun getSessionDetailIntent(context: Context, sessionId: String, sessionDetail: String): Intent { + fun getSessionDetailIntent(context: Context, + sessionId: String, + sessionDetail: String): Intent { return Intent(context, MainActivity::class.java).apply { putExtra(EXTRA_SESSIONID, sessionId) putExtra(EXTRA_SESSION_DETAILS, sessionDetail) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt index 291d3a1..4bad314 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt @@ -6,11 +6,11 @@ import android.os.Handler import android.support.v7.app.AppCompatActivity import android.view.View import android.view.animation.AccelerateDecelerateInterpolator -import com.mentalmachines.droidcon_boston.R +import android.view.animation.AlphaAnimation import android.view.animation.Animation import android.view.animation.Animation.AnimationListener -import android.view.animation.AlphaAnimation -import kotlinx.android.synthetic.main.splash_activity.logo_text +import com.mentalmachines.droidcon_boston.R +import kotlinx.android.synthetic.main.splash_activity.* class SplashActivity : AppCompatActivity() { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index d57a8b0..c0e2719 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -61,7 +61,8 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { return super.onOptionsItemSelected(item) } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.agenda_day_fragment, container, false) } @@ -111,8 +112,8 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { Log.d(TAG, "Event: $data") if (data != null) { val scheduleRow = data.toScheduleRow(key) - if (scheduleRow.date == dayFilter && (!onlyMyAgenda - || onlyMyAgenda && userAgendaRepo.isSessionBookmarked(scheduleRow.id))) { + if (scheduleRow.date == dayFilter && (!onlyMyAgenda || onlyMyAgenda && userAgendaRepo.isSessionBookmarked( + scheduleRow.id))) { rows.add(scheduleRow) } } @@ -144,9 +145,8 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { items.add(item) } - val sortedItems = items.sortedWith( - compareBy { it.itemData.utcStartTimeString } - .thenBy { it.roomSortOrder }) + val sortedItems = + items.sortedWith(compareBy { it.itemData.utcStartTimeString }.thenBy { it.roomSortOrder }) headerAdapter = FlexibleAdapter(sortedItems) headerAdapter!!.addListener(this) @@ -154,11 +154,15 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { agendaRecyler.addItemDecoration(FlexibleItemDecoration(agendaRecyler.context).withDefaultDivider()) headerAdapter!!.expandItemsAtStartUp().setDisplayHeadersAtStartUp(true) - EmptyViewHelper(headerAdapter, emptyStateView, null,null) + EmptyViewHelper(headerAdapter, emptyStateView, null, null) } override fun onItemClick(view: View, position: Int): Boolean { - val adapterItem = try { headerAdapter?.getItem(position) } catch (e: Exception) { null } + val adapterItem = try { + headerAdapter?.getItem(position) + } catch (e: Exception) { + null + } if (adapterItem is ScheduleAdapterItem) { val itemData = adapterItem.itemData if (itemData.primarySpeakerName.isNullorEmpty()) { @@ -169,7 +173,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { val i = Intent(Intent.ACTION_VIEW) i.data = Uri.parse(url) val packageManager = activity?.packageManager - if (packageManager !=null && i.resolveActivity(packageManager) != null) { + if (packageManager != null && i.resolveActivity(packageManager) != null) { startActivity(i) } return false diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt index 2baf820..ec57c6e 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt @@ -4,8 +4,9 @@ import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager import com.mentalmachines.droidcon_boston.data.Schedule -class AgendaDayPagerAdapter internal constructor(fm: FragmentManager, private val myAgenda: Boolean) - : FixedFragmentStatePagerAdapter(fm) { +class AgendaDayPagerAdapter internal constructor(fm: FragmentManager, + private val myAgenda: Boolean) : + FixedFragmentStatePagerAdapter(fm) { private val PAGE_COUNT = 2 private val tabTitles = arrayOf("Day 1", "Day 2") @@ -16,8 +17,7 @@ class AgendaDayPagerAdapter internal constructor(fm: FragmentManager, private va override fun getItem(position: Int): Fragment { return AgendaDayFragment.newInstance(myAgenda, - if (position == 0) Schedule.MONDAY else Schedule.TUESDAY - ) + if (position == 0) Schedule.MONDAY else Schedule.TUESDAY) } override fun getPageTitle(position: Int): CharSequence? { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt index 5be9cc6..d394103 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt @@ -6,13 +6,13 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.mentalmachines.droidcon_boston.R -import kotlinx.android.synthetic.main.agenda_fragment.tablayout -import kotlinx.android.synthetic.main.agenda_fragment.viewpager -import java.util.Calendar +import kotlinx.android.synthetic.main.agenda_fragment.* +import java.util.* class AgendaFragment : Fragment() { - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.agenda_fragment, container, false) } @@ -25,8 +25,7 @@ class AgendaFragment : Fragment() { private fun setupDayPager(savedInstanceState: Bundle?) { - viewpager.adapter = AgendaDayPagerAdapter(childFragmentManager, - isMyAgenda()) + viewpager.adapter = AgendaDayPagerAdapter(childFragmentManager, isMyAgenda()) tablayout.setupWithViewPager(viewpager) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt index aa12260..0cef7f2 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt @@ -5,8 +5,7 @@ import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentStatePagerAdapter import android.support.v4.view.PagerAdapter import android.view.ViewGroup - -import java.util.WeakHashMap +import java.util.* /** * See https://stackoverflow.com/questions/13695649/refresh-images-on-fragmentstatepageradapter-on-resuming-activity @@ -59,9 +58,7 @@ abstract class FixedFragmentStatePagerAdapter(fm: FragmentManager) : FragmentSta */ private fun findFragmentPositionHashMap(fragmentObj: Fragment): Int { for (position in mFragments.keys) { - if (position != null && - mFragments[position] != null && - mFragments[position] === fragmentObj) { + if (position != null && mFragments[position] != null && mFragments[position] === fragmentObj) { return position } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt index f610a86..06fc9a8 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt @@ -25,7 +25,7 @@ import java.util.* */ class ScheduleAdapterItem internal constructor(val itemData: Schedule.ScheduleRow, header: ScheduleAdapterItemHeader) : - AbstractSectionableItem(header) { + AbstractSectionableItem(header) { private var startTime: Date = Date() @@ -61,7 +61,8 @@ class ScheduleAdapterItem internal constructor(val itemData: Schedule.ScheduleRo return R.layout.schedule_item } - override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { + override fun createViewHolder(view: View, + adapter: FlexibleAdapter>): ViewHolder { return ScheduleAdapterItem.ViewHolder(view, adapter) } @@ -77,10 +78,9 @@ class ScheduleAdapterItem internal constructor(val itemData: Schedule.ScheduleRo holder.speaker.visibility = View.GONE holder.time.visibility = View.GONE - holder.bookmarkIndicator.visibility = if (userAgendaRepo.isSessionBookmarked(itemData.id)) - View.VISIBLE - else - View.INVISIBLE + holder.bookmarkIndicator.visibility = + if (userAgendaRepo.isSessionBookmarked(itemData.id)) View.VISIBLE + else View.INVISIBLE holder.sessionLayout.visibility = View.VISIBLE holder.title.text = itemData.talkTitle holder.room.text = itemData.room @@ -102,28 +102,26 @@ class ScheduleAdapterItem internal constructor(val itemData: Schedule.ScheduleRo holder.speaker.text = itemData.speakerNames.joinToString(separator = ", ") holder.room.text = itemData.room - holder.speakerCount.visibility = if (itemData.speakerCount > 1) View.VISIBLE else View.GONE + holder.speakerCount.visibility = + if (itemData.speakerCount > 1) View.VISIBLE else View.GONE holder.speakerCount.text = String.format("+%d", itemData.speakerCount - 1) val context = holder.title.context - Glide.with(context) - .load(itemData.photoUrlMap[itemData.primarySpeakerName]) - .transform(CircleTransform(context)) - .placeholder(R.drawable.emo_im_cool) - .crossFade() - .into(holder.avatar) + Glide.with(context).load(itemData.photoUrlMap[itemData.primarySpeakerName]) + .transform(CircleTransform(context)).placeholder(R.drawable.emo_im_cool).crossFade() + .into(holder.avatar) - holder.bookmarkIndicator.visibility = if (userAgendaRepo.isSessionBookmarked(itemData.id)) - View.VISIBLE - else - View.INVISIBLE + holder.bookmarkIndicator.visibility = + if (userAgendaRepo.isSessionBookmarked(itemData.id)) View.VISIBLE + else View.INVISIBLE addBackgroundRipple(holder) } val availableColor = if (itemData.isOver) R.color.colorGray else R.color.colorAccent - holder.availableIndicator.setBackgroundColor(ContextCompat.getColor(holder.availableIndicator.context, availableColor)) + holder.availableIndicator.setBackgroundColor(ContextCompat.getColor(holder.availableIndicator.context, + availableColor)) } private fun addBackgroundRipple(holder: ViewHolder) { @@ -163,7 +161,9 @@ class ScheduleAdapterItem internal constructor(val itemData: Schedule.ScheduleRo findViews(view) } - constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) : super(view, adapter, stickyHeader) { + constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) : super(view, + adapter, + stickyHeader) { findViews(view) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt index f922809..3ee94a3 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt @@ -12,8 +12,8 @@ import eu.davidea.viewholders.FlexibleViewHolder /** * Sticky header for schedule view */ -class ScheduleAdapterItemHeader internal constructor(private val sessionTime: String) - : AbstractHeaderItem() { +class ScheduleAdapterItemHeader internal constructor(private val sessionTime: String) : + AbstractHeaderItem() { override fun equals(other: Any?): Boolean { if (other is ScheduleAdapterItemHeader) { @@ -31,7 +31,8 @@ class ScheduleAdapterItemHeader internal constructor(private val sessionTime: St return R.layout.schedule_item_header } - override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { + override fun createViewHolder(view: View, + adapter: FlexibleAdapter>): ViewHolder { return ScheduleAdapterItemHeader.ViewHolder(view, adapter, true) } @@ -47,13 +48,13 @@ class ScheduleAdapterItemHeader internal constructor(private val sessionTime: St lateinit var header: TextView - constructor(view: View, adapter: FlexibleAdapter<*>) - : super(view, adapter) { + constructor(view: View, adapter: FlexibleAdapter<*>) : super(view, adapter) { findViews(view) } - internal constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) - : super(view, adapter, stickyHeader) { + internal constructor(view: View, + adapter: FlexibleAdapter<*>, + stickyHeader: Boolean) : super(view, adapter, stickyHeader) { findViews(view) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt index d2903a9..908dcaf 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt @@ -45,7 +45,8 @@ class AgendaDetailFragment : Fragment() { get() = UserAgendaRepo.getInstance(fab_agenda_detail_bookmark.context) - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.agenda_detail_fragment, container, false) @@ -54,7 +55,8 @@ class AgendaDetailFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - scheduleRowItem = gson.fromJson(arguments!!.getString(Schedule.SCHEDULE_ITEM_ROW), ScheduleRow::class.java) + scheduleRowItem = gson.fromJson(arguments!!.getString(Schedule.SCHEDULE_ITEM_ROW), + ScheduleRow::class.java) fetchDataFromFirebase() populateView() @@ -66,8 +68,11 @@ class AgendaDetailFragment : Fragment() { private fun populateView() { tv_agenda_detail_title.text = scheduleRowItem.talkTitle - tv_agenda_detail_room.text = resources.getString(R.string.str_agenda_detail_room, scheduleRowItem.room) - tv_agenda_detail_time.text = resources.getString(R.string.str_agenda_detail_time, scheduleRowItem.startTime, scheduleRowItem.endTime) + tv_agenda_detail_room.text = + resources.getString(R.string.str_agenda_detail_room, scheduleRowItem.room) + tv_agenda_detail_time.text = resources.getString(R.string.str_agenda_detail_time, + scheduleRowItem.startTime, + scheduleRowItem.endTime) fab_agenda_detail_bookmark.setOnClickListener({ @@ -82,10 +87,9 @@ class AgendaDetailFragment : Fragment() { } Snackbar.make(agendaDetailView, - if (nextBookmarkStatus) - getString(R.string.saved_agenda_item) - else getString(R.string.removed_agenda_item), - Snackbar.LENGTH_SHORT).show() + if (nextBookmarkStatus) getString(R.string.saved_agenda_item) + else getString(R.string.removed_agenda_item), + Snackbar.LENGTH_SHORT).show() showBookmarkStatus(scheduleDetail!!) } @@ -117,8 +121,7 @@ class AgendaDetailFragment : Fragment() { } private fun fetchDataFromFirebase() { - firebaseHelper.speakerDatabase.orderByChild("name") - .addValueEventListener(dataListener) + firebaseHelper.speakerDatabase.orderByChild("name").addValueEventListener(dataListener) } override fun onDestroyView() { @@ -178,27 +181,24 @@ class AgendaDetailFragment : Fragment() { // add speakerName as a child to the relative layout agendaDetailView.addView(tempImg) - Glide.with(this) - .load(itemData.photoUrlMap[speakerName]) - .transform(CircleTransform(tempImg.context)) - .placeholder(R.drawable.emo_im_cool) - .crossFade() - .into(tempImg) + Glide.with(this).load(itemData.photoUrlMap[speakerName]) + .transform(CircleTransform(tempImg.context)).placeholder(R.drawable.emo_im_cool) + .crossFade().into(tempImg) tempImg.setOnClickListener { _ -> val eventSpeaker = eventSpeakers[speakerName] val arguments = Bundle() - arguments.putString(EventSpeaker.SPEAKER_ITEM_ROW, gson.toJson(eventSpeaker, EventSpeaker::class.java)) + arguments.putString(EventSpeaker.SPEAKER_ITEM_ROW, + gson.toJson(eventSpeaker, EventSpeaker::class.java)) val speakerDetailFragment = SpeakerDetailFragment() speakerDetailFragment.arguments = arguments val fragmentManager = activity?.supportFragmentManager fragmentManager?.beginTransaction() - ?.add(R.id.fragment_container, speakerDetailFragment) - ?.addToBackStack(null) - ?.commit() + ?.add(R.id.fragment_container, speakerDetailFragment)?.addToBackStack(null) + ?.commit() } } tv_agenda_detail_speaker_name.text = speakerNames @@ -210,7 +210,8 @@ class AgendaDetailFragment : Fragment() { showBookmarkStatus(scheduleDetail) tv_agenda_detail_title.text = scheduleDetail.listRow.talkTitle - tv_agenda_detail_description.text = scheduleDetail.listRow.talkDescription.getHtmlFormattedSpanned() + tv_agenda_detail_description.text = + scheduleDetail.listRow.talkDescription.getHtmlFormattedSpanned() tv_agenda_detail_description.movementMethod = LinkMovementMethod.getInstance() } @@ -218,24 +219,24 @@ class AgendaDetailFragment : Fragment() { private fun showBookmarkStatus(scheduleDetail: ScheduleDetail) { val userAgendaRepo = userAgendaRepo val context = fab_agenda_detail_bookmark.context - fab_agenda_detail_bookmark.backgroundTintList = if (userAgendaRepo.isSessionBookmarked(scheduleDetail.id)) - ColorStateList.valueOf(ContextCompat.getColor(context, R.color.colorAccent)) - else - ColorStateList.valueOf(ContextCompat.getColor(context, R.color.colorLightGray)) + fab_agenda_detail_bookmark.backgroundTintList = + if (userAgendaRepo.isSessionBookmarked(scheduleDetail.id)) ColorStateList.valueOf( + ContextCompat.getColor(context, R.color.colorAccent)) + else ColorStateList.valueOf(ContextCompat.getColor(context, R.color.colorLightGray)) } companion object { - fun addDetailFragmentToStack(supportFragmentManager: FragmentManager, itemData: Schedule.ScheduleRow) { + fun addDetailFragmentToStack(supportFragmentManager: FragmentManager, + itemData: Schedule.ScheduleRow) { val arguments = Bundle() - arguments.putString(Schedule.SCHEDULE_ITEM_ROW, gson.toJson(itemData, ScheduleRow::class.java)) + arguments.putString(Schedule.SCHEDULE_ITEM_ROW, + gson.toJson(itemData, ScheduleRow::class.java)) val agendaDetailFragment = AgendaDetailFragment() agendaDetailFragment.arguments = arguments supportFragmentManager.beginTransaction() - .add(R.id.fragment_container, agendaDetailFragment) - .addToBackStack(null) - .commit() + .add(R.id.fragment_container, agendaDetailFragment).addToBackStack(null).commit() } } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt index 374bdfb..b770c31 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt @@ -15,19 +15,15 @@ import com.mentalmachines.droidcon_boston.utils.getHtmlFormattedSpanned import com.mentalmachines.droidcon_boston.utils.loadUriInCustomTab import com.mentalmachines.droidcon_boston.views.MainActivity import com.mentalmachines.droidcon_boston.views.transform.CircleTransform -import kotlinx.android.synthetic.main.speaker_detail_fragment.imgv_linkedin -import kotlinx.android.synthetic.main.speaker_detail_fragment.imgv_speaker_detail_avatar -import kotlinx.android.synthetic.main.speaker_detail_fragment.imgv_twitter -import kotlinx.android.synthetic.main.speaker_detail_fragment.tv_speaker_detail_description -import kotlinx.android.synthetic.main.speaker_detail_fragment.tv_speaker_detail_designation -import kotlinx.android.synthetic.main.speaker_detail_fragment.tv_speaker_detail_name +import kotlinx.android.synthetic.main.speaker_detail_fragment.* class SpeakerDetailFragment : Fragment() { private val firebaseHelper = FirebaseHelper.instance - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.speaker_detail_fragment, container, false) @@ -36,7 +32,8 @@ class SpeakerDetailFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val itemData = gson.fromJson(arguments!!.getString(EventSpeaker.SPEAKER_ITEM_ROW), EventSpeaker::class.java) + val itemData = gson.fromJson(arguments!!.getString(EventSpeaker.SPEAKER_ITEM_ROW), + EventSpeaker::class.java) populateView(itemData) if (activity is MainActivity) { @@ -47,7 +44,8 @@ class SpeakerDetailFragment : Fragment() { private fun populateView(itemData: EventSpeaker) { tv_speaker_detail_name.text = itemData.name - tv_speaker_detail_designation.text = String.format("%s \n@ %s", itemData.title, itemData.org) + tv_speaker_detail_designation.text = + String.format("%s \n@ %s", itemData.title, itemData.org) tv_speaker_detail_description.text = itemData.bio.getHtmlFormattedSpanned() tv_speaker_detail_description.movementMethod = LinkMovementMethod.getInstance() @@ -55,7 +53,9 @@ class SpeakerDetailFragment : Fragment() { val twitterHandle = itemData.socialProfiles?.get("twitter") if (!twitterHandle.isNullOrEmpty()) { imgv_twitter.setOnClickListener({ - activity?.loadUriInCustomTab(String.format("%s%s", resources.getString(R.string.twitter_link), twitterHandle)) + activity?.loadUriInCustomTab(String.format("%s%s", + resources.getString(R.string.twitter_link), + twitterHandle)) }) } else { imgv_twitter.visibility = View.GONE @@ -65,18 +65,17 @@ class SpeakerDetailFragment : Fragment() { val linkedinHandle = itemData.socialProfiles?.get("linkedIn") if (!linkedinHandle.isNullOrEmpty()) { imgv_linkedin.setOnClickListener({ - activity?.loadUriInCustomTab(String.format("%s%s", resources.getString(R.string.linkedin_profile_link), linkedinHandle)) + activity?.loadUriInCustomTab(String.format("%s%s", + resources.getString(R.string.linkedin_profile_link), + linkedinHandle)) }) } else { imgv_linkedin.visibility = View.GONE } - Glide.with(activity) - .load(itemData.pictureUrl) - .transform(CircleTransform(imgv_speaker_detail_avatar.context)) - .placeholder(R.drawable.emo_im_cool) - .crossFade() - .into(imgv_speaker_detail_avatar) + Glide.with(activity).load(itemData.pictureUrl) + .transform(CircleTransform(imgv_speaker_detail_avatar.context)) + .placeholder(R.drawable.emo_im_cool).crossFade().into(imgv_speaker_detail_avatar) } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt index 6c14a1d..118e9c8 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt @@ -17,9 +17,8 @@ import eu.davidea.viewholders.FlexibleViewHolder /** * Used for displaying the FAQ items */ -class FaqAdapterItem internal constructor(val itemData: Answer, - header: FaqAdapterItemHeader) : - AbstractSectionableItem(header) { +class FaqAdapterItem internal constructor(val itemData: Answer, header: FaqAdapterItemHeader) : + AbstractSectionableItem(header) { override fun equals(other: Any?): Boolean { if (other is FaqAdapterItem) { @@ -37,7 +36,8 @@ class FaqAdapterItem internal constructor(val itemData: Answer, return R.layout.faq_item } - override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { + override fun createViewHolder(view: View, + adapter: FlexibleAdapter>): ViewHolder { return FaqAdapterItem.ViewHolder(view, adapter) } @@ -49,11 +49,8 @@ class FaqAdapterItem internal constructor(val itemData: Answer, holder.faq_text.text = itemData.answer if (!TextUtils.isEmpty(itemData.photoLink)) { val context = holder.faq_text.context - Glide.with(context) - .load(itemData.photoLink) - .crossFade() - .centerCrop() - .into(holder.faq_photo) + Glide.with(context).load(itemData.photoLink).crossFade().centerCrop() + .into(holder.faq_photo) holder.faq_photo.visibility = View.VISIBLE } else { holder.faq_photo.visibility = View.GONE diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt index 25b62a2..1d41d89 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt @@ -12,8 +12,8 @@ import eu.davidea.viewholders.FlexibleViewHolder /** * Header for FAQ view */ -class FaqAdapterItemHeader internal constructor(private val question: String) - : AbstractHeaderItem() { +class FaqAdapterItemHeader internal constructor(private val question: String) : + AbstractHeaderItem() { override fun equals(other: Any?): Boolean { if (other is FaqAdapterItemHeader) { @@ -31,7 +31,8 @@ class FaqAdapterItemHeader internal constructor(private val question: String) return R.layout.faq_header } - override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { + override fun createViewHolder(view: View, + adapter: FlexibleAdapter>): ViewHolder { return FaqAdapterItemHeader.ViewHolder(view, adapter, true) } @@ -47,13 +48,13 @@ class FaqAdapterItemHeader internal constructor(private val question: String) lateinit var header: TextView - constructor(view: View, adapter: FlexibleAdapter<*>) - : super(view, adapter) { + constructor(view: View, adapter: FlexibleAdapter<*>) : super(view, adapter) { findViews(view) } - internal constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) - : super(view, adapter, stickyHeader) { + internal constructor(view: View, + adapter: FlexibleAdapter<*>, + stickyHeader: Boolean) : super(view, adapter, stickyHeader) { findViews(view) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt index fb1a840..f1badf1 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt @@ -9,9 +9,10 @@ import android.widget.ImageView import android.widget.TextView import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.modal.SocialModal -import java.util.ArrayList +import java.util.* -internal class RVSocialListAdapter(private var socialList: ArrayList) : Adapter() { +internal class RVSocialListAdapter(private var socialList: ArrayList) : + Adapter() { inner class ListViewHolder(itemView: View) : ViewHolder(itemView) { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt index a68cc80..d9427d5 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt @@ -13,14 +13,16 @@ import com.mentalmachines.droidcon_boston.utils.DividerItemDecoration import com.mentalmachines.droidcon_boston.utils.RVItemClickListener import com.mentalmachines.droidcon_boston.utils.RVItemClickListener.OnItemClickListener import com.mentalmachines.droidcon_boston.utils.loadUriInCustomTab -import kotlinx.android.synthetic.main.social_fragment.social_rv -import java.util.ArrayList +import kotlinx.android.synthetic.main.social_fragment.* +import java.util.* class SocialFragment : Fragment() { private lateinit var socialList: ArrayList - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.social_fragment, container, false) } @@ -40,23 +42,30 @@ class SocialFragment : Fragment() { social_rv.adapter = RVSocialListAdapter(socialList) // Set On Click - social_rv.addOnItemTouchListener(RVItemClickListener(context!!, object : OnItemClickListener { - override fun onItemClick(view: View, position: Int) { - context?.loadUriInCustomTab(socialList[position].link.toString()) - } - })) + social_rv.addOnItemTouchListener(RVItemClickListener(context!!, + object : OnItemClickListener { + override fun onItemClick(view: View, position: Int) { + context?.loadUriInCustomTab(socialList[position].link.toString()) + } + })) } private fun prepareSocialList(): ArrayList { val socialList = ArrayList() - socialList.add(SocialModal(R.drawable.social_facebook, getString(R.string.social_title_facebook), - getString(R.string.facebook_link))) - socialList.add(SocialModal(R.drawable.social_instagram, getString(R.string.social_title_instagram), - getString(R.string.instagram_link))) - socialList.add(SocialModal(R.drawable.social_linkedin, getString(R.string.social_title_linkedin), - getString(R.string.linkedin_link))) - socialList.add(SocialModal(R.drawable.social_twitter, getString(R.string.social_title_twitter), - String.format("%s%s", resources.getString(R.string.twitter_link), getString(string.droidconbos_twitter_handle)))) + socialList.add(SocialModal(R.drawable.social_facebook, + getString(R.string.social_title_facebook), + getString(R.string.facebook_link))) + socialList.add(SocialModal(R.drawable.social_instagram, + getString(R.string.social_title_instagram), + getString(R.string.instagram_link))) + socialList.add(SocialModal(R.drawable.social_linkedin, + getString(R.string.social_title_linkedin), + getString(R.string.linkedin_link))) + socialList.add(SocialModal(R.drawable.social_twitter, + getString(R.string.social_title_twitter), + String.format("%s%s", + resources.getString(R.string.twitter_link), + getString(string.droidconbos_twitter_handle)))) return socialList } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt index 46349ec..8bdc259 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt @@ -18,22 +18,20 @@ import eu.davidea.viewholders.FlexibleViewHolder * Used for displaying speaker list items on the all speakers "Speakers" page. */ class SpeakerAdapterItem internal constructor(val itemData: EventSpeaker) : - AbstractFlexibleItem() { + AbstractFlexibleItem() { override fun bindViewHolder(adapter: FlexibleAdapter>?, - holder: ViewHolder, position: Int, payloads: MutableList?) { + holder: ViewHolder, + position: Int, + payloads: MutableList?) { holder.name.text = itemData.name holder.bio.text = itemData.bio.getHtmlFormattedSpanned() val context = holder.name.context - Glide.with(context) - .load(itemData.pictureUrl) - .transform(CircleTransform(context)) - .placeholder(R.drawable.emo_im_cool) - .crossFade() - .into(holder.avatar) + Glide.with(context).load(itemData.pictureUrl).transform(CircleTransform(context)) + .placeholder(R.drawable.emo_im_cool).crossFade().into(holder.avatar) } override fun equals(other: Any?): Boolean { @@ -52,7 +50,8 @@ class SpeakerAdapterItem internal constructor(val itemData: EventSpeaker) : return R.layout.speaker_item } - override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { + override fun createViewHolder(view: View, + adapter: FlexibleAdapter>): ViewHolder { return SpeakerAdapterItem.ViewHolder(view, adapter) } @@ -68,7 +67,9 @@ class SpeakerAdapterItem internal constructor(val itemData: EventSpeaker) : findViews(view) } - constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) : super(view, adapter, stickyHeader) { + constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) : super(view, + adapter, + stickyHeader) { findViews(view) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt index 857c0ab..bffbc1d 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt @@ -26,7 +26,8 @@ class SpeakerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private val firebaseHelper = FirebaseHelper.instance private lateinit var speakerAdapter: FlexibleAdapter - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.speaker_fragment, container, false) @@ -73,16 +74,15 @@ class SpeakerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { val arguments = Bundle() - arguments.putString(EventSpeaker.SPEAKER_ITEM_ROW, gson.toJson(itemData, EventSpeaker::class.java)) + arguments.putString(EventSpeaker.SPEAKER_ITEM_ROW, + gson.toJson(itemData, EventSpeaker::class.java)) val speakerDetailFragment = SpeakerDetailFragment() speakerDetailFragment.arguments = arguments val fragmentManager = activity?.supportFragmentManager - fragmentManager?.beginTransaction() - ?.add(R.id.fragment_container, speakerDetailFragment) - ?.addToBackStack(null) - ?.commit() + fragmentManager?.beginTransaction()?.add(R.id.fragment_container, speakerDetailFragment) + ?.addToBackStack(null)?.commit() } return true diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/transform/CircleTransform.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/transform/CircleTransform.kt index e88ba9e..74100b5 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/transform/CircleTransform.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/transform/CircleTransform.kt @@ -12,7 +12,10 @@ import com.bumptech.glide.load.resource.bitmap.BitmapTransformation class CircleTransform(context: Context) : BitmapTransformation(context) { - override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap? { + override fun transform(pool: BitmapPool, + toTransform: Bitmap, + outWidth: Int, + outHeight: Int): Bitmap? { return circleCrop(pool, toTransform) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt index f0ef738..a6a9e55 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt @@ -18,11 +18,12 @@ import eu.davidea.viewholders.FlexibleViewHolder * Used for displaying volunteer list items on the all volunteers "volunteers" page. */ class VolunteerAdapterItem internal constructor(val itemData: VolunteerEvent) : - AbstractFlexibleItem() { + AbstractFlexibleItem() { override fun bindViewHolder(adapter: FlexibleAdapter>?, - holder: ViewHolder, position: Int, payloads: MutableList?) { - + holder: ViewHolder, + position: Int, + payloads: MutableList?) { var bodyText = itemData.position @@ -35,12 +36,8 @@ class VolunteerAdapterItem internal constructor(val itemData: VolunteerEvent) : val context = holder.name.context - Glide.with(context) - .load(itemData.pictureUrl) - .transform(CircleTransform(context)) - .placeholder(R.drawable.emo_im_cool) - .crossFade() - .into(holder.avatar) + Glide.with(context).load(itemData.pictureUrl).transform(CircleTransform(context)) + .placeholder(R.drawable.emo_im_cool).crossFade().into(holder.avatar) } override fun equals(other: Any?): Boolean { @@ -59,7 +56,8 @@ class VolunteerAdapterItem internal constructor(val itemData: VolunteerEvent) : return R.layout.volunteer_item } - override fun createViewHolder(view: View, adapter: FlexibleAdapter>): ViewHolder { + override fun createViewHolder(view: View, + adapter: FlexibleAdapter>): ViewHolder { return ViewHolder(view, adapter) } @@ -75,7 +73,9 @@ class VolunteerAdapterItem internal constructor(val itemData: VolunteerEvent) : findViews(view) } - constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) : super(view, adapter, stickyHeader) { + constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) : super(view, + adapter, + stickyHeader) { findViews(view) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt index d61ba6a..586272a 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt @@ -18,7 +18,7 @@ import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper import com.mentalmachines.droidcon_boston.utils.loadUriInCustomTab import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.common.FlexibleItemDecoration -import kotlinx.android.synthetic.main.volunteer_fragment.volunteer_recycler +import kotlinx.android.synthetic.main.volunteer_fragment.* class VolunteerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { @@ -26,7 +26,8 @@ class VolunteerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private val firebaseHelper = FirebaseHelper.instance private lateinit var volunteerAdapter: FlexibleAdapter - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.volunteer_fragment, container, false) @@ -62,14 +63,17 @@ class VolunteerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { } private fun fetchDataFromFirebase() { - firebaseHelper.volunteerDatabase.orderByChild("firstName").addValueEventListener(dataListener) + firebaseHelper.volunteerDatabase.orderByChild("firstName") + .addValueEventListener(dataListener) } override fun onItemClick(view: View, position: Int): Boolean { val item = volunteerAdapter.getItem(position) if (item is VolunteerAdapterItem && !item.itemData.twitter.isEmpty()) { val context = activity as Context - context.loadUriInCustomTab(String.format("%s%s", resources.getString(R.string.twitter_link), item.itemData.twitter)) + context.loadUriInCustomTab(String.format("%s%s", + resources.getString(R.string.twitter_link), + item.itemData.twitter)) return false } diff --git a/Droidcon-Boston/app/src/main/res/drawable/bg_social_btn.xml b/Droidcon-Boston/app/src/main/res/drawable/bg_social_btn.xml index 3006778..0a7a729 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/bg_social_btn.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/bg_social_btn.xml @@ -1,8 +1,6 @@ - - + + \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/drawable/circular_textview_accent_background.xml b/Droidcon-Boston/app/src/main/res/drawable/circular_textview_accent_background.xml index 2bde016..80af40f 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/circular_textview_accent_background.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/circular_textview_accent_background.xml @@ -1,6 +1,6 @@ + android:shape="oval"> + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z" /> diff --git a/Droidcon-Boston/app/src/main/res/drawable/ic_agenda.xml b/Droidcon-Boston/app/src/main/res/drawable/ic_agenda.xml index 7322c92..b08dce9 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/ic_agenda.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/ic_agenda.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M17,10L7,10v2h10v-2zM19,3h-1L18,1h-2v2L8,3L8,1L6,1v2L5,3c-1.11,0 -1.99,0.9 -1.99,2L3,19c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19L5,8h14v11zM14,14L7,14v2h7v-2z" /> diff --git a/Droidcon-Boston/app/src/main/res/drawable/ic_coc.xml b/Droidcon-Boston/app/src/main/res/drawable/ic_coc.xml index 99b5867..c5418b5 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/ic_coc.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/ic_coc.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M13,12h7v1.5h-7zM13,9.5h7L20,11h-7zM13,14.5h7L20,16h-7zM21,4L3,4c-1.1,0 -2,0.9 -2,2v13c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2L23,6c0,-1.1 -0.9,-2 -2,-2zM21,19h-9L12,6h9v13z" /> diff --git a/Droidcon-Boston/app/src/main/res/drawable/ic_faq.xml b/Droidcon-Boston/app/src/main/res/drawable/ic_faq.xml index 4a3eb4f..1681cc0 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/ic_faq.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/ic_faq.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M19,3h-4.18C14.4,1.84 13.3,1 12,1c-1.3,0 -2.4,0.84 -2.82,2L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM12,3c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM14,17L7,17v-2h7v2zM17,13L7,13v-2h10v2zM17,9L7,9L7,7h10v2z" /> diff --git a/Droidcon-Boston/app/src/main/res/drawable/ic_my_schedule.xml b/Droidcon-Boston/app/src/main/res/drawable/ic_my_schedule.xml index 811d5ac..b3b6e16 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/ic_my_schedule.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/ic_my_schedule.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M18,2H6c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zM6,4h5v8l-2.5,-1.5L6,12V4z" /> diff --git a/Droidcon-Boston/app/src/main/res/drawable/ic_social.xml b/Droidcon-Boston/app/src/main/res/drawable/ic_social.xml index 49d69e0..564406c 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/ic_social.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/ic_social.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M20,12c0,-1.1 0.9,-2 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2v4c1.1,0 1.99,0.9 1.99,2s-0.89,2 -2,2v4c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2v-4c-1.1,0 -2,-0.9 -2,-2zM15.58,16.8L12,14.5l-3.58,2.3 1.08,-4.12 -3.29,-2.69 4.24,-0.25L12,5.8l1.54,3.95 4.24,0.25 -3.29,2.69 1.09,4.11z" /> diff --git a/Droidcon-Boston/app/src/main/res/drawable/ic_speakers.xml b/Droidcon-Boston/app/src/main/res/drawable/ic_speakers.xml index 4cfd869..603c006 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/ic_speakers.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/ic_speakers.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3s1.34,3 3,3zM8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8s1.34,3 3,3zM8,13c-2.33,0 -7,1.17 -7,3.5L1,19h14v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5zM16,13c-0.29,0 -0.62,0.02 -0.97,0.05 1.16,0.84 1.97,1.97 1.97,3.45L17,19h6v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5z" /> diff --git a/Droidcon-Boston/app/src/main/res/drawable/ic_star.xml b/Droidcon-Boston/app/src/main/res/drawable/ic_star.xml index a87ca09..a2ebf35 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/ic_star.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/ic_star.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z" /> diff --git a/Droidcon-Boston/app/src/main/res/drawable/ic_volunteers.xml b/Droidcon-Boston/app/src/main/res/drawable/ic_volunteers.xml index 90ed54d..8a31e99 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/ic_volunteers.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/ic_volunteers.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M19,2L5,2c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h4l3,3 3,-3h4c1.1,0 2,-0.9 2,-2L21,4c0,-1.1 -0.9,-2 -2,-2zM12,5.3c1.49,0 2.7,1.21 2.7,2.7 0,1.49 -1.21,2.7 -2.7,2.7 -1.49,0 -2.7,-1.21 -2.7,-2.7 0,-1.49 1.21,-2.7 2.7,-2.7zM18,16L6,16v-0.9c0,-2 4,-3.1 6,-3.1s6,1.1 6,3.1v0.9z" /> diff --git a/Droidcon-Boston/app/src/main/res/drawable/social_back.xml b/Droidcon-Boston/app/src/main/res/drawable/social_back.xml index 1844a00..498f397 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/social_back.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/social_back.xml @@ -1,5 +1,6 @@ - + - + \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/drawable/social_press.xml b/Droidcon-Boston/app/src/main/res/drawable/social_press.xml index 372f1f8..390e53a 100644 --- a/Droidcon-Boston/app/src/main/res/drawable/social_press.xml +++ b/Droidcon-Boston/app/src/main/res/drawable/social_press.xml @@ -1,5 +1,6 @@ - + - + \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/about_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/about_fragment.xml index cae2c18..97dd2e4 100644 --- a/Droidcon-Boston/app/src/main/res/layout/about_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/about_fragment.xml @@ -13,30 +13,30 @@ android:id="@+id/imageView2" android:layout_width="match_parent" android:layout_height="200dp" + android:contentDescription="Navigation Header" android:scaleType="centerCrop" - android:src="@drawable/navigation_header_image" - android:contentDescription="Navigation Header" /> + android:src="@drawable/navigation_header_image" /> + android:src="@drawable/logo_text" /> + tools:text="@tools:sample/lorem/random" /> \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml index 0f484b4..c1ab862 100644 --- a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml @@ -1,7 +1,5 @@ - - - + @@ -9,9 +7,9 @@ android:id="@+id/agenda_recycler" android:layout_width="match_parent" android:layout_height="match_parent" - android:scrollbars="vertical" - android:background="@color/colorBackground"/> + android:background="@color/colorBackground" + android:scrollbars="vertical" /> - + diff --git a/Droidcon-Boston/app/src/main/res/layout/agenda_detail_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/agenda_detail_fragment.xml index cc1fdf0..3db61e0 100644 --- a/Droidcon-Boston/app/src/main/res/layout/agenda_detail_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/agenda_detail_fragment.xml @@ -27,12 +27,12 @@ style="@android:style/TextAppearance.Medium" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" android:layout_alignParentStart="true" + android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginTop="30dp" - android:paddingEnd="16dp" android:paddingStart="16dp" + android:paddingEnd="16dp" android:textColor="@android:color/white" android:textSize="24sp" android:textStyle="bold" @@ -43,11 +43,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@+id/tv_agenda_detail_time" - android:layout_alignParentLeft="true" android:layout_alignParentStart="true" + android:layout_alignParentLeft="true" android:fontFamily="sans-serif" - android:paddingEnd="16dp" android:paddingStart="16dp" + android:paddingEnd="16dp" android:textColor="@android:color/white" android:textSize="14sp" android:textStyle="bold" @@ -61,8 +61,8 @@ android:layout_alignBottom="@+id/imgv_header_bg" android:layout_marginBottom="16dp" android:fontFamily="sans-serif" - android:paddingEnd="16dp" android:paddingStart="16dp" + android:paddingEnd="16dp" android:textColor="@color/colorAccent" android:textSize="18sp" tools:text="10:30 am - 11:15 am" /> @@ -71,12 +71,12 @@ android:id="@+id/fab_agenda_detail_bookmark" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_below="@+id/tv_agenda_detail_room" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" - android:layout_below="@+id/tv_agenda_detail_room" + android:layout_marginTop="10dp" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" - android:layout_marginTop="10dp" android:tint="@android:color/white" app:backgroundTint="@color/colorLightGray" app:srcCompat="@drawable/ic_star" /> diff --git a/Droidcon-Boston/app/src/main/res/layout/agenda_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/agenda_fragment.xml index 4851290..7a05680 100644 --- a/Droidcon-Boston/app/src/main/res/layout/agenda_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/agenda_fragment.xml @@ -8,11 +8,11 @@ + app:tabTextAppearance="@style/AppTabText" /> + android:textSize="17sp" /> diff --git a/Droidcon-Boston/app/src/main/res/layout/empty_view.xml b/Droidcon-Boston/app/src/main/res/layout/empty_view.xml index f22a227..a742f12 100644 --- a/Droidcon-Boston/app/src/main/res/layout/empty_view.xml +++ b/Droidcon-Boston/app/src/main/res/layout/empty_view.xml @@ -1,8 +1,7 @@ - + android:textColor="?android:textColorSecondary" /> diff --git a/Droidcon-Boston/app/src/main/res/layout/faq_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/faq_fragment.xml index 56c1b56..923efcb 100644 --- a/Droidcon-Boston/app/src/main/res/layout/faq_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/faq_fragment.xml @@ -1,9 +1,8 @@ - \ No newline at end of file + android:scrollbars="vertical" /> \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/faq_header.xml b/Droidcon-Boston/app/src/main/res/layout/faq_header.xml index 27fcd67..638894b 100644 --- a/Droidcon-Boston/app/src/main/res/layout/faq_header.xml +++ b/Droidcon-Boston/app/src/main/res/layout/faq_header.xml @@ -1,14 +1,13 @@ - - - + android:textSize="17sp" + tools:text="Answer to your question" /> + android:contentDescription="@string/hint_faq_photo" + tools:src="@drawable/logo_text" /> \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/nav_header.xml b/Droidcon-Boston/app/src/main/res/layout/nav_header.xml index c44f77d..abc3bf5 100644 --- a/Droidcon-Boston/app/src/main/res/layout/nav_header.xml +++ b/Droidcon-Boston/app/src/main/res/layout/nav_header.xml @@ -7,19 +7,19 @@ + android:src="@drawable/navigation_header_image" /> + android:src="@drawable/logo_text" /> \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/schedule_item.xml b/Droidcon-Boston/app/src/main/res/layout/schedule_item.xml index 2d6cf94..6043bcf 100644 --- a/Droidcon-Boston/app/src/main/res/layout/schedule_item.xml +++ b/Droidcon-Boston/app/src/main/res/layout/schedule_item.xml @@ -1,12 +1,11 @@ - + android:foreground="?attr/selectableItemBackground"> + android:paddingTop="16dp" + android:paddingBottom="16dp"> + android:textSize="18sp" + tools:text="Title" /> + android:textSize="16sp" + tools:text="10:00 am - 10:30 am" /> + android:textSize="12sp" /> + android:textSize="13sp" + tools:text="Room Blah Blah" /> + tools:text="A Speaker, asdf asfafsafdasffas, asdf asfadsfasdf, asdf, asdfsadf, asdf, asdfasdfasf, asdf, asdf" /> @@ -117,16 +116,17 @@ android:layout_width="90dp" android:layout_height="90dp" android:layout_gravity="center_vertical"> + + tools:src="@drawable/bg_social_btn" /> + + tools:visibility="visible" /> + android:layout_marginRight="8dp" + android:contentDescription="@string/hint_bookmark" + android:tint="@color/colorStar" + app:srcCompat="@drawable/ic_star" /> \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/schedule_item_header.xml b/Droidcon-Boston/app/src/main/res/layout/schedule_item_header.xml index 4b123df..cd8a3ca 100644 --- a/Droidcon-Boston/app/src/main/res/layout/schedule_item_header.xml +++ b/Droidcon-Boston/app/src/main/res/layout/schedule_item_header.xml @@ -1,6 +1,5 @@ - + android:background="@color/colorBackground" /> + + android:id="@+id/header_text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:fontFamily="sans-serif" + android:maxLines="1" + android:paddingLeft="16dp" + android:paddingTop="2dp" + android:paddingRight="16dp" + android:paddingBottom="2dp" + android:textColor="@android:color/black" + android:textSize="14sp" + tools:text="10:30am" /> + + android:background="@color/colorBackground" /> \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/social_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/social_fragment.xml index 7b1b3c4..417de89 100644 --- a/Droidcon-Boston/app/src/main/res/layout/social_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/social_fragment.xml @@ -1,6 +1,6 @@ \ No newline at end of file + android:layout_height="match_parent" + android:background="@android:color/white" /> \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/social_list_item.xml b/Droidcon-Boston/app/src/main/res/layout/social_list_item.xml index d5050e0..6c68838 100644 --- a/Droidcon-Boston/app/src/main/res/layout/social_list_item.xml +++ b/Droidcon-Boston/app/src/main/res/layout/social_list_item.xml @@ -10,8 +10,8 @@ android:id="@+id/social_item_img" android:layout_width="48dp" android:layout_height="48dp" - tools:src="@drawable/social_facebook" - android:contentDescription="Social Icon" /> + android:contentDescription="Social Icon" + tools:src="@drawable/social_facebook" /> + tools:text="Facebook" /> \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/speaker_detail_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/speaker_detail_fragment.xml index 65a237e..2385e12 100644 --- a/Droidcon-Boston/app/src/main/res/layout/speaker_detail_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/speaker_detail_fragment.xml @@ -38,8 +38,8 @@ android:layout_below="@+id/imgv_speaker_detail_avatar" android:layout_marginTop="@dimen/margin_normal" android:gravity="center" - android:paddingEnd="@dimen/def_padding" android:paddingStart="@dimen/def_padding" + android:paddingEnd="@dimen/def_padding" android:textColor="@android:color/white" android:textSize="24sp" android:textStyle="bold" @@ -50,13 +50,13 @@ android:id="@+id/tv_speaker_detail_designation" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" android:layout_below="@+id/tv_speaker_detail_name" + android:layout_alignParentStart="true" + android:layout_alignParentLeft="true" android:fontFamily="sans-serif" android:gravity="center" - android:paddingEnd="@dimen/def_padding_large" android:paddingStart="@dimen/def_padding_large" + android:paddingEnd="@dimen/def_padding_large" android:textColor="@color/colorAccent" android:textSize="18sp" tools:text="Software Engineer @ Company" /> @@ -69,20 +69,20 @@ android:layout_alignEnd="@id/imgv_header_bg" android:layout_alignRight="@id/imgv_header_bg" android:layout_marginBottom="-20dp" - android:paddingEnd="@dimen/def_padding" - android:paddingLeft="@dimen/def_padding" - android:paddingRight="@dimen/def_padding" + android:orientation="horizontal" android:paddingStart="@dimen/def_padding" - android:orientation="horizontal"> + android:paddingLeft="@dimen/def_padding" + android:paddingEnd="@dimen/def_padding" + android:paddingRight="@dimen/def_padding"> diff --git a/Droidcon-Boston/app/src/main/res/layout/speaker_item.xml b/Droidcon-Boston/app/src/main/res/layout/speaker_item.xml index c6d0c44..3ee23fb 100644 --- a/Droidcon-Boston/app/src/main/res/layout/speaker_item.xml +++ b/Droidcon-Boston/app/src/main/res/layout/speaker_item.xml @@ -11,14 +11,14 @@ + tools:visibility="visible" /> + android:paddingTop="8dp" + android:paddingBottom="8dp"> - @@ -8,14 +7,14 @@ android:id="@+id/logo_text" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:foregroundGravity="center" android:layout_gravity="center" - android:maxWidth="600dp" android:adjustViewBounds="true" + android:contentDescription="@string/app_name" android:focusable="true" android:focusableInTouchMode="true" - android:contentDescription="@string/app_name" + android:foregroundGravity="center" + android:maxWidth="600dp" android:padding="75dp" - android:src="@drawable/logo_text"/> + android:src="@drawable/logo_text" /> \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/volunteer_item.xml b/Droidcon-Boston/app/src/main/res/layout/volunteer_item.xml index 819e96c..2db96a8 100644 --- a/Droidcon-Boston/app/src/main/res/layout/volunteer_item.xml +++ b/Droidcon-Boston/app/src/main/res/layout/volunteer_item.xml @@ -11,14 +11,14 @@ + tools:visibility="visible" /> + android:paddingTop="8dp" + android:paddingBottom="8dp"> - - + + \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/Droidcon-Boston/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 4ae7d12..be31618 100644 --- a/Droidcon-Boston/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/Droidcon-Boston/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/Droidcon-Boston/app/src/test/java/com/mentalmachines/droidcon_boston/data/ScheduleTest.kt b/Droidcon-Boston/app/src/test/java/com/mentalmachines/droidcon_boston/data/ScheduleTest.kt index 6e1ecc3..befa76d 100644 --- a/Droidcon-Boston/app/src/test/java/com/mentalmachines/droidcon_boston/data/ScheduleTest.kt +++ b/Droidcon-Boston/app/src/test/java/com/mentalmachines/droidcon_boston/data/ScheduleTest.kt @@ -1,9 +1,10 @@ package com.mentalmachines.droidcon_boston.data import com.mentalmachines.droidcon_boston.data.Schedule.ScheduleRow -import org.junit.* -import org.junit.Assert.* -import java.util.Arrays +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import java.util.* class ScheduleTest { From 51de5cdadd70b0a4f2bd9e5d35984ffc3497c51b Mon Sep 17 00:00:00 2001 From: Nishant Srivastava Date: Sat, 3 Nov 2018 02:43:05 +0100 Subject: [PATCH 005/173] =?UTF-8?q?=F0=9F=9A=A7=20code=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../droidcon_boston/data/FirebaseDatabase.kt | 2 +- .../droidcon_boston/firebase/FirebaseHelper.kt | 3 +-- .../droidcon_boston/views/AboutFragment.kt | 2 +- .../droidcon_boston/views/CocFragment.kt | 2 +- .../droidcon_boston/views/FAQFragment.kt | 2 +- .../droidcon_boston/views/MainActivity.kt | 2 +- .../droidcon_boston/views/SplashActivity.kt | 8 ++++---- .../views/agenda/AgendaDayFragment.kt | 8 ++++---- .../agenda/FixedFragmentStatePagerAdapter.kt | 2 +- .../views/detail/AgendaDetailFragment.kt | 16 +++++++--------- .../views/detail/SpeakerDetailFragment.kt | 8 ++++---- .../views/social/RVSocialListAdapter.kt | 3 +-- .../views/speaker/SpeakerFragment.kt | 2 +- .../views/volunteer/VolunteerFragment.kt | 2 +- 14 files changed, 29 insertions(+), 33 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt index 3b09af9..0e70c02 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt @@ -31,7 +31,7 @@ open class FirebaseDatabase { var endTime: String = "", var trackSortOrder: Int = 0) { - val conferenceTZ = ZoneId.of("America/New_York") + private val conferenceTZ: ZoneId = ZoneId.of("America/New_York") fun getLocalStartTime(): LocalDateTime { return ZonedDateTime.parse(startTime).withZoneSameInstant(ZoneId.systemDefault()) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/FirebaseHelper.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/FirebaseHelper.kt index 39fd91a..3ef0c84 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/FirebaseHelper.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/FirebaseHelper.kt @@ -6,7 +6,7 @@ import com.google.firebase.database.FirebaseDatabase class FirebaseHelper private constructor() { - private val database: FirebaseDatabase + private val database: FirebaseDatabase = FirebaseDatabase.getInstance() private val mainDatabase: DatabaseReference val eventDatabase: DatabaseReference val speakerDatabase: DatabaseReference @@ -16,7 +16,6 @@ class FirebaseHelper private constructor() { val volunteerDatabase: DatabaseReference init { - this.database = FirebaseDatabase.getInstance() // Enable disk persistence, https://firebase.google.com/docs/database/android/offline-capabilities this.database.setPersistenceEnabled(true) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt index b8f6d96..bf85b43 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt @@ -36,7 +36,7 @@ class AboutFragment : Fragment() { firebaseHelper.aboutDatabase.removeEventListener(dataListener) } - val dataListener: ValueEventListener = object : ValueEventListener { + private val dataListener: ValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { tv_about_description.text = dataSnapshot.getValue(String::class.java)?.getHtmlFormattedSpanned() diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt index 00402b5..deacefd 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt @@ -38,7 +38,7 @@ class CocFragment : Fragment() { firebaseHelper.cocDatabase.removeEventListener(dataListener) } - val dataListener: ValueEventListener = object : ValueEventListener { + private val dataListener: ValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { tv_coc.text = dataSnapshot.getValue(String::class.java)?.getHtmlFormattedSpanned() diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt index 338ca1f..0fb8dff 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt @@ -48,7 +48,7 @@ class FAQFragment : Fragment(), FlexibleAdapter.OnItemClickListener { firebaseHelper.faqDatabase.removeEventListener(dataListener) } - val dataListener: ValueEventListener = object : ValueEventListener { + private val dataListener: ValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { val rows = ArrayList() for (faqSnapshot in dataSnapshot.children) { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index f86f13a..6253e85 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -93,7 +93,7 @@ class MainActivity : AppCompatActivity() { } fun uncheckAllMenuItems() { - processMenuItems({ _ -> true }, { item -> item.setChecked(false).isChecked }, true) + processMenuItems({ true }, { item -> item.setChecked(false).isChecked }, true) } private fun processMenuItems(titleMatcher: (MenuItem) -> Boolean, diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt index 4bad314..b22ef52 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt @@ -29,7 +29,7 @@ class SplashActivity : AppCompatActivity() { private fun startMainActivity() { val intent = Intent(this, MainActivity::class.java) startActivity(intent) - overridePendingTransition(0, 0); + overridePendingTransition(0, 0) finish() } @@ -43,7 +43,7 @@ class SplashActivity : AppCompatActivity() { override fun onAnimationStart(animation: Animation) {} override fun onAnimationRepeat(animation: Animation) {} override fun onAnimationEnd(animation: Animation) { - logo_text.setVisibility(View.GONE) + logo_text.visibility = View.GONE startMainActivity() } }) @@ -52,7 +52,7 @@ class SplashActivity : AppCompatActivity() { } companion object { - val FADE_DURATION: Long = 750 - val SPLASH_DURATION: Long = 1500 + const val FADE_DURATION: Long = 750 + const val SPLASH_DURATION: Long = 1500 } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index c0e2719..72ed2aa 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -54,7 +54,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { android.R.id.home -> { val fragmentManager = activity?.supportFragmentManager if (fragmentManager?.backStackEntryCount!! > 0) { - fragmentManager?.popBackStack() + fragmentManager.popBackStack() } } } @@ -103,7 +103,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { agendaRecyler.adapter?.notifyDataSetChanged() } - val dataListener: ValueEventListener = object : ValueEventListener { + private val dataListener: ValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { val rows = ArrayList() for (roomSnapshot in dataSnapshot.children) { @@ -166,7 +166,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { if (adapterItem is ScheduleAdapterItem) { val itemData = adapterItem.itemData if (itemData.primarySpeakerName.isNullorEmpty()) { - val url = itemData.photoUrlMap.get(itemData.primarySpeakerName) + val url = itemData.photoUrlMap[itemData.primarySpeakerName] if (!url.isNullorEmpty()) { // event where info URL is in the photoUrls string @@ -181,7 +181,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { } activity?.let { - AgendaDetailFragment.addDetailFragmentToStack(it.supportFragmentManager, itemData); + AgendaDetailFragment.addDetailFragmentToStack(it.supportFragmentManager, itemData) } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt index 0cef7f2..9144cdb 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt @@ -53,7 +53,7 @@ abstract class FixedFragmentStatePagerAdapter(fm: FragmentManager) : FragmentSta /** * Find the location of a fragment in the hashmap if it being view - * @param object the Fragment we want to check for + * @param fragmentObj the Fragment we want to check for * @return the position if found else -1 */ private fun findFragmentPositionHashMap(fragmentObj: Fragment): Int { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt index 908dcaf..9c1ba90 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt @@ -74,7 +74,7 @@ class AgendaDetailFragment : Fragment() { scheduleRowItem.startTime, scheduleRowItem.endTime) - fab_agenda_detail_bookmark.setOnClickListener({ + fab_agenda_detail_bookmark.setOnClickListener { if (scheduleDetail != null) { val nextBookmarkStatus = !userAgendaRepo.isSessionBookmarked(scheduleDetail!!.id) @@ -86,24 +86,22 @@ class AgendaDetailFragment : Fragment() { NotificationUtils(context).cancelNotificationAlarm(scheduleRowItem.id) } - Snackbar.make(agendaDetailView, - if (nextBookmarkStatus) getString(R.string.saved_agenda_item) - else getString(R.string.removed_agenda_item), - Snackbar.LENGTH_SHORT).show() + Snackbar.make(agendaDetailView, if (nextBookmarkStatus) getString(R.string.saved_agenda_item) + else getString(R.string.removed_agenda_item), Snackbar.LENGTH_SHORT).show() showBookmarkStatus(scheduleDetail!!) } - }) + } populateSpeakersInformation(scheduleRowItem) } - val dataListener: ValueEventListener = object : ValueEventListener { + private val dataListener: ValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { for (speakerSnapshot in dataSnapshot.children) { val speaker = speakerSnapshot.getValue(EventSpeaker::class.java) if (speaker != null) { - eventSpeakers.put(speaker.name, speaker) + eventSpeakers[speaker.name] = speaker if (scheduleRowItem.primarySpeakerName == speaker.name) { scheduleDetail = speaker.toScheduleDetail(scheduleRowItem) @@ -185,7 +183,7 @@ class AgendaDetailFragment : Fragment() { .transform(CircleTransform(tempImg.context)).placeholder(R.drawable.emo_im_cool) .crossFade().into(tempImg) - tempImg.setOnClickListener { _ -> + tempImg.setOnClickListener { val eventSpeaker = eventSpeakers[speakerName] val arguments = Bundle() diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt index b770c31..4e74991 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt @@ -52,11 +52,11 @@ class SpeakerDetailFragment : Fragment() { val twitterHandle = itemData.socialProfiles?.get("twitter") if (!twitterHandle.isNullOrEmpty()) { - imgv_twitter.setOnClickListener({ + imgv_twitter.setOnClickListener { activity?.loadUriInCustomTab(String.format("%s%s", resources.getString(R.string.twitter_link), twitterHandle)) - }) + } } else { imgv_twitter.visibility = View.GONE } @@ -64,11 +64,11 @@ class SpeakerDetailFragment : Fragment() { val linkedinHandle = itemData.socialProfiles?.get("linkedIn") if (!linkedinHandle.isNullOrEmpty()) { - imgv_linkedin.setOnClickListener({ + imgv_linkedin.setOnClickListener { activity?.loadUriInCustomTab(String.format("%s%s", resources.getString(R.string.linkedin_profile_link), linkedinHandle)) - }) + } } else { imgv_linkedin.visibility = View.GONE } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt index f1badf1..0c212eb 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt @@ -16,12 +16,11 @@ internal class RVSocialListAdapter(private var socialList: ArrayList() for (speakerSnapshot in dataSnapshot.children) { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt index 586272a..b4da81f 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt @@ -44,7 +44,7 @@ class VolunteerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { firebaseHelper.volunteerDatabase.removeEventListener(dataListener) } - val dataListener: ValueEventListener = object : ValueEventListener { + private val dataListener: ValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { val rows = ArrayList() for (volunteerSnapshot in dataSnapshot.children) { From d0ac6abe0af8517905692d4e89f9059ba13feed9 Mon Sep 17 00:00:00 2001 From: Nishant Srivastava Date: Mon, 5 Nov 2018 20:17:59 +0100 Subject: [PATCH 006/173] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactoring:=20mig?= =?UTF-8?q?rate=20to=20androidx=20support=20libs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Droidcon-Boston/app/build.gradle | 14 +++++++------- .../utils/DividerItemDecoration.kt | 13 +++++++------ .../droidcon_boston/utils/ExtensionFunctions.kt | 4 ++-- .../droidcon_boston/utils/NotificationUtils.kt | 2 +- .../droidcon_boston/utils/RVItemClickListener.kt | 2 +- .../droidcon_boston/views/AboutFragment.kt | 2 +- .../droidcon_boston/views/CocFragment.kt | 2 +- .../droidcon_boston/views/FAQFragment.kt | 6 +++--- .../droidcon_boston/views/MainActivity.kt | 9 ++++----- .../droidcon_boston/views/SplashActivity.kt | 2 +- .../views/agenda/AgendaDayFragment.kt | 8 ++++---- .../views/agenda/AgendaDayPagerAdapter.kt | 4 ++-- .../views/agenda/AgendaFragment.kt | 2 +- .../agenda/FixedFragmentStatePagerAdapter.kt | 8 ++++---- .../views/agenda/ScheduleAdapterItem.kt | 4 ++-- .../views/agenda/ScheduleAdapterItemHeader.kt | 2 +- .../views/detail/AgendaDetailFragment.kt | 14 +++++++------- .../views/detail/SpeakerDetailFragment.kt | 3 +-- .../droidcon_boston/views/faq/FaqAdapterItem.kt | 5 ++--- .../views/faq/FaqAdapterItemHeader.kt | 2 +- .../views/social/RVSocialListAdapter.kt | 4 ++-- .../views/social/SocialFragment.kt | 8 ++++---- .../views/speaker/SpeakerAdapterItem.kt | 2 +- .../views/speaker/SpeakerFragment.kt | 6 +++--- .../views/volunteer/VolunteerAdapterItem.kt | 2 +- .../views/volunteer/VolunteerFragment.kt | 6 +++--- .../src/main/res/layout/agenda_day_fragment.xml | 2 +- .../main/res/layout/agenda_detail_fragment.xml | 2 +- .../app/src/main/res/layout/agenda_fragment.xml | 4 ++-- .../app/src/main/res/layout/faq_fragment.xml | 2 +- .../app/src/main/res/layout/main_activity.xml | 16 ++++++++-------- .../app/src/main/res/layout/social_fragment.xml | 2 +- .../app/src/main/res/layout/speaker_fragment.xml | 2 +- .../src/main/res/layout/volunteer_fragment.xml | 2 +- Droidcon-Boston/gradle.properties | 4 +++- 35 files changed, 86 insertions(+), 86 deletions(-) diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index 7d48f6e..9b94c68 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -12,7 +12,7 @@ android { targetSdkVersion 28 versionCode 17 versionName "2.0.9" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true @@ -59,12 +59,12 @@ dependencies { testImplementation "junit:junit:4.12" // Support - final support = "28.0.0" - implementation "com.android.support:appcompat-v7:$support" - implementation "com.android.support:support-v4:$support" - implementation "com.android.support:cardview-v7:$support" - implementation "com.android.support:design:$support" - implementation "com.android.support:customtabs:$support" + final support = '1.0.0' + implementation "androidx.appcompat:appcompat:1.0.1" + implementation "androidx.legacy:legacy-support-v4:$support" + implementation "androidx.cardview:cardview:$support" + implementation "com.google.android.material:material:$support" + implementation "androidx.browser:browser:$support" // Firebase implementation "com.google.firebase:firebase-messaging:17.3.4" diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt index 06cb613..dea6586 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt @@ -4,11 +4,12 @@ import android.content.Context import android.graphics.Canvas import android.graphics.Rect import android.graphics.drawable.Drawable -import android.support.v4.view.ViewCompat -import android.support.v7.widget.LinearLayoutManager -import android.support.v7.widget.RecyclerView -import android.support.v7.widget.RecyclerView.State import android.view.View +import androidx.core.view.ViewCompat +import androidx.recyclerview.widget.LinearLayoutManager.HORIZONTAL +import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView.State class DividerItemDecoration(context: Context, orientation: Int) : RecyclerView.ItemDecoration() { @@ -82,8 +83,8 @@ class DividerItemDecoration(context: Context, orientation: Int) : RecyclerView.I private val ATTRS = intArrayOf(android.R.attr.listDivider) - const val HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL + const val HORIZONTAL_LIST = HORIZONTAL - const val VERTICAL_LIST = LinearLayoutManager.VERTICAL + const val VERTICAL_LIST = VERTICAL } } \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt index 7c4438e..bd2d074 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt @@ -2,8 +2,8 @@ package com.mentalmachines.droidcon_boston.utils import android.content.Context import android.net.Uri -import android.support.customtabs.CustomTabsIntent -import android.support.v4.content.ContextCompat +import androidx.browser.customtabs.CustomTabsIntent +import androidx.core.content.ContextCompat import android.text.Html import android.text.Spanned import com.mentalmachines.droidcon_boston.R diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt index 210bfb7..2952257 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt @@ -10,7 +10,7 @@ import android.content.pm.PackageManager import android.graphics.Color import android.os.Build import android.os.Build.VERSION_CODES -import android.support.v4.app.NotificationCompat +import androidx.core.app.NotificationCompat import android.text.TextUtils import android.util.Log import com.google.firebase.database.DataSnapshot diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt index defd5a5..508274e 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt @@ -1,10 +1,10 @@ package com.mentalmachines.droidcon_boston.utils import android.content.Context -import android.support.v7.widget.RecyclerView import android.view.GestureDetector import android.view.MotionEvent import android.view.View +import androidx.recyclerview.widget.RecyclerView open class RVItemClickListener(context: Context, private val itemClickListener: OnItemClickListener?) : diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt index bf85b43..52686fa 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/AboutFragment.kt @@ -1,12 +1,12 @@ package com.mentalmachines.droidcon_boston.views import android.os.Bundle -import android.support.v4.app.Fragment import android.text.method.LinkMovementMethod import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError import com.google.firebase.database.ValueEventListener diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt index deacefd..a1f2501 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/CocFragment.kt @@ -2,12 +2,12 @@ package com.mentalmachines.droidcon_boston.views import android.os.Bundle -import android.support.v4.app.Fragment import android.text.method.LinkMovementMethod import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError import com.google.firebase.database.ValueEventListener diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt index 0fb8dff..59c62ae 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt @@ -3,13 +3,12 @@ package com.mentalmachines.droidcon_boston.views import android.content.Intent import android.net.Uri import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v7.widget.LinearLayoutManager import android.text.TextUtils import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError import com.google.firebase.database.ValueEventListener @@ -85,7 +84,8 @@ class FAQFragment : Fragment(), FlexibleAdapter.OnItemClickListener { } } - faq_recycler.layoutManager = LinearLayoutManager(faq_recycler.context) + faq_recycler.layoutManager = + androidx.recyclerview.widget.LinearLayoutManager(faq_recycler.context) headerAdapter = FlexibleAdapter(items) headerAdapter.addListener(this) faq_recycler.adapter = headerAdapter diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index 6253e85..82fc0f4 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -4,13 +4,12 @@ import android.content.Context import android.content.Intent import android.content.res.Configuration import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v4.view.GravityCompat -import android.support.v7.app.ActionBarDrawerToggle -import android.support.v7.app.AppCompatActivity import android.text.TextUtils import android.view.Gravity import android.view.MenuItem +import androidx.appcompat.app.ActionBarDrawerToggle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.GravityCompat import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.R.id import com.mentalmachines.droidcon_boston.R.string @@ -200,7 +199,7 @@ class MainActivity : AppCompatActivity() { updateToolbarTitle(title) // Get the fragment by tag - var fragment: Fragment? = supportFragmentManager.findFragmentByTag(title) + var fragment: androidx.fragment.app.Fragment? = supportFragmentManager.findFragmentByTag(title) if (fragment == null) { // Initialize the fragment based on tag diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt index b22ef52..ab85f1b 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/SplashActivity.kt @@ -3,12 +3,12 @@ package com.mentalmachines.droidcon_boston.views import android.content.Intent import android.os.Bundle import android.os.Handler -import android.support.v7.app.AppCompatActivity import android.view.View import android.view.animation.AccelerateDecelerateInterpolator import android.view.animation.AlphaAnimation import android.view.animation.Animation import android.view.animation.Animation.AnimationListener +import androidx.appcompat.app.AppCompatActivity import com.mentalmachines.droidcon_boston.R import kotlinx.android.synthetic.main.splash_activity.* diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index 72ed2aa..259878c 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -3,14 +3,13 @@ package com.mentalmachines.droidcon_boston.views.agenda import android.content.Intent import android.net.Uri import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v7.widget.LinearLayoutManager -import android.support.v7.widget.RecyclerView import android.util.Log import android.view.LayoutInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.RecyclerView import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError import com.google.firebase.database.ValueEventListener @@ -75,7 +74,8 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { agendaRecyler = view.findViewById(R.id.agenda_recycler) emptyStateView = view.findViewById(R.id.empty_view) - agendaRecyler.layoutManager = LinearLayoutManager(activity?.applicationContext) + agendaRecyler.layoutManager = + androidx.recyclerview.widget.LinearLayoutManager(activity?.applicationContext) onlyMyAgenda = arguments?.getBoolean(ARG_MY_AGENDA) ?: false diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt index ec57c6e..5ce4442 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt @@ -1,7 +1,7 @@ package com.mentalmachines.droidcon_boston.views.agenda -import android.support.v4.app.Fragment -import android.support.v4.app.FragmentManager +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager import com.mentalmachines.droidcon_boston.data.Schedule class AgendaDayPagerAdapter internal constructor(fm: FragmentManager, diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt index d394103..1fd067e 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt @@ -1,10 +1,10 @@ package com.mentalmachines.droidcon_boston.views.agenda import android.os.Bundle -import android.support.v4.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment import com.mentalmachines.droidcon_boston.R import kotlinx.android.synthetic.main.agenda_fragment.* import java.util.* diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt index 9144cdb..aca92c5 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/FixedFragmentStatePagerAdapter.kt @@ -1,10 +1,10 @@ package com.mentalmachines.droidcon_boston.views.agenda -import android.support.v4.app.Fragment -import android.support.v4.app.FragmentManager -import android.support.v4.app.FragmentStatePagerAdapter -import android.support.v4.view.PagerAdapter import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentStatePagerAdapter +import androidx.viewpager.widget.PagerAdapter import java.util.* /** diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt index 06fc9a8..f65a2ed 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt @@ -1,12 +1,12 @@ package com.mentalmachines.droidcon_boston.views.agenda -import android.support.v4.content.ContextCompat -import android.support.v7.widget.RecyclerView import android.util.Log import android.util.TypedValue import android.view.View import android.widget.ImageView import android.widget.TextView +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.data.Schedule diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt index 3ee94a3..a9ebb48 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt @@ -1,8 +1,8 @@ package com.mentalmachines.droidcon_boston.views.agenda -import android.support.v7.widget.RecyclerView import android.view.View import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView import com.mentalmachines.droidcon_boston.R import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.AbstractHeaderItem diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt index 9c1ba90..37888e3 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt @@ -2,10 +2,10 @@ package com.mentalmachines.droidcon_boston.views.detail import android.content.res.ColorStateList import android.os.Bundle -import android.support.design.widget.Snackbar -import android.support.v4.app.Fragment -import android.support.v4.app.FragmentManager -import android.support.v4.content.ContextCompat +import com.google.android.material.snackbar.Snackbar +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.core.content.ContextCompat import android.text.method.LinkMovementMethod import android.util.Log import android.view.LayoutInflater @@ -86,8 +86,8 @@ class AgendaDetailFragment : Fragment() { NotificationUtils(context).cancelNotificationAlarm(scheduleRowItem.id) } - Snackbar.make(agendaDetailView, if (nextBookmarkStatus) getString(R.string.saved_agenda_item) - else getString(R.string.removed_agenda_item), Snackbar.LENGTH_SHORT).show() + com.google.android.material.snackbar.Snackbar.make(agendaDetailView, if (nextBookmarkStatus) getString(R.string.saved_agenda_item) + else getString(R.string.removed_agenda_item), com.google.android.material.snackbar.Snackbar.LENGTH_SHORT).show() showBookmarkStatus(scheduleDetail!!) } @@ -224,7 +224,7 @@ class AgendaDetailFragment : Fragment() { } companion object { - fun addDetailFragmentToStack(supportFragmentManager: FragmentManager, + fun addDetailFragmentToStack(supportFragmentManager: androidx.fragment.app.FragmentManager, itemData: Schedule.ScheduleRow) { val arguments = Bundle() arguments.putString(Schedule.SCHEDULE_ITEM_ROW, diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt index 4e74991..5d03f72 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt @@ -1,7 +1,6 @@ package com.mentalmachines.droidcon_boston.views.detail import android.os.Bundle -import android.support.v4.app.Fragment import android.text.method.LinkMovementMethod import android.view.LayoutInflater import android.view.View @@ -18,7 +17,7 @@ import com.mentalmachines.droidcon_boston.views.transform.CircleTransform import kotlinx.android.synthetic.main.speaker_detail_fragment.* -class SpeakerDetailFragment : Fragment() { +class SpeakerDetailFragment : androidx.fragment.app.Fragment() { private val firebaseHelper = FirebaseHelper.instance diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt index 118e9c8..5f1307c 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt @@ -1,6 +1,5 @@ package com.mentalmachines.droidcon_boston.views.faq -import android.support.v7.widget.RecyclerView import android.text.TextUtils import android.util.TypedValue import android.view.View @@ -37,11 +36,11 @@ class FaqAdapterItem internal constructor(val itemData: Answer, header: FaqAdapt } override fun createViewHolder(view: View, - adapter: FlexibleAdapter>): ViewHolder { + adapter: FlexibleAdapter>): ViewHolder { return FaqAdapterItem.ViewHolder(view, adapter) } - override fun bindViewHolder(adapter: FlexibleAdapter>, + override fun bindViewHolder(adapter: FlexibleAdapter>, holder: FaqAdapterItem.ViewHolder, position: Int, payloads: MutableList) { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt index 1d41d89..8840b77 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt @@ -1,8 +1,8 @@ package com.mentalmachines.droidcon_boston.views.faq -import android.support.v7.widget.RecyclerView import android.view.View import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView import com.mentalmachines.droidcon_boston.R import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.AbstractHeaderItem diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt index 0c212eb..940c7cb 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt @@ -1,12 +1,12 @@ package com.mentalmachines.droidcon_boston.views.social -import android.support.v7.widget.RecyclerView.Adapter -import android.support.v7.widget.RecyclerView.ViewHolder import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView.Adapter +import androidx.recyclerview.widget.RecyclerView.ViewHolder import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.modal.SocialModal import java.util.* diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt index d9427d5..4b21e93 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt @@ -1,11 +1,11 @@ package com.mentalmachines.droidcon_boston.views.social import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v7.widget.LinearLayoutManager import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.R.string import com.mentalmachines.droidcon_boston.modal.SocialModal @@ -32,10 +32,10 @@ class SocialFragment : Fragment() { super.onViewCreated(view, savedInstanceState) // Set Layout Manager - social_rv.layoutManager = LinearLayoutManager(activity) + social_rv.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(activity) // Set the divider - social_rv.addItemDecoration(DividerItemDecoration(activity!!, LinearLayoutManager.VERTICAL)) + social_rv.addItemDecoration(DividerItemDecoration(activity!!, androidx.recyclerview.widget.LinearLayoutManager.VERTICAL)) socialList = prepareSocialList() // Set Adapter diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt index 8bdc259..a437b46 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt @@ -1,9 +1,9 @@ package com.mentalmachines.droidcon_boston.views.speaker -import android.support.v7.widget.RecyclerView import android.view.View import android.widget.ImageView import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.data.FirebaseDatabase.EventSpeaker diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt index 5a59f16..6e5e242 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt @@ -2,12 +2,11 @@ package com.mentalmachines.droidcon_boston.views.speaker import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v7.widget.LinearLayoutManager import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError import com.google.firebase.database.ValueEventListener @@ -90,7 +89,8 @@ class SpeakerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private fun setupSpeakerAdapter(rows: ArrayList) { val items = rows.map { SpeakerAdapterItem(it) } - speaker_recycler.layoutManager = LinearLayoutManager(speaker_recycler.context) + speaker_recycler.layoutManager = + androidx.recyclerview.widget.LinearLayoutManager(speaker_recycler.context) speakerAdapter = FlexibleAdapter(items) speakerAdapter.addListener(this) speaker_recycler.adapter = speakerAdapter diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt index a6a9e55..1d34478 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt @@ -1,9 +1,9 @@ package com.mentalmachines.droidcon_boston.views.volunteer -import android.support.v7.widget.RecyclerView import android.view.View import android.widget.ImageView import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.data.FirebaseDatabase.VolunteerEvent diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt index b4da81f..511f99f 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt @@ -3,12 +3,11 @@ package com.mentalmachines.droidcon_boston.views.volunteer import android.content.Context import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v7.widget.LinearLayoutManager import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError import com.google.firebase.database.ValueEventListener @@ -83,7 +82,8 @@ class VolunteerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private fun setupVolunteerAdapter(rows: ArrayList) { val items = rows.map { VolunteerAdapterItem(it) } - volunteer_recycler.layoutManager = LinearLayoutManager(volunteer_recycler.context) + volunteer_recycler.layoutManager = + androidx.recyclerview.widget.LinearLayoutManager(volunteer_recycler.context) volunteerAdapter = FlexibleAdapter(items) volunteerAdapter.addListener(this) volunteer_recycler.adapter = volunteerAdapter diff --git a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml index c1ab862..cf195b0 100644 --- a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml @@ -3,7 +3,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - - - - - - - - + - + - - \ No newline at end of file + \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/social_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/social_fragment.xml index 417de89..62c0610 100644 --- a/Droidcon-Boston/app/src/main/res/layout/social_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/social_fragment.xml @@ -1,5 +1,5 @@ - - - Date: Sun, 18 Nov 2018 10:24:51 +0100 Subject: [PATCH 007/173] =?UTF-8?q?=F0=9F=8E=A8=20added:=20project=20based?= =?UTF-8?q?=20code=20style=20files.=20-=20To=20stick=20to=20project=20base?= =?UTF-8?q?d=20codestyle,=20simply=20sync=20with=20the=20project=20and=20c?= =?UTF-8?q?hoose=20"Project"=20in=20the=20code=20style=20section=20of=20th?= =?UTF-8?q?e=20IDE=20preferences?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Droidcon-Boston/.idea/codeStyles/Project.xml | 172 ++++++++++++++++++ .../.idea/codeStyles/codeStyleConfig.xml | 5 + 2 files changed, 177 insertions(+) create mode 100644 Droidcon-Boston/.idea/codeStyles/Project.xml create mode 100644 Droidcon-Boston/.idea/codeStyles/codeStyleConfig.xml diff --git a/Droidcon-Boston/.idea/codeStyles/Project.xml b/Droidcon-Boston/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..f874795 --- /dev/null +++ b/Droidcon-Boston/.idea/codeStyles/Project.xml @@ -0,0 +1,172 @@ + + + + \ No newline at end of file diff --git a/Droidcon-Boston/.idea/codeStyles/codeStyleConfig.xml b/Droidcon-Boston/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/Droidcon-Boston/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file From 25bd88ec33b6af5db3d90c9d7b4dc2d7ee3abed9 Mon Sep 17 00:00:00 2001 From: Nishant Srivastava Date: Sun, 18 Nov 2018 10:33:14 +0100 Subject: [PATCH 008/173] =?UTF-8?q?=F0=9F=8E=A8=20structure/format:=20re-r?= =?UTF-8?q?an=20the=20code=20format=20tool=20(just=20to=20be=20sure=20and?= =?UTF-8?q?=20consistent=20with=20the=20project=20based=20code=20styles)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../droidcon_boston/data/FirebaseDatabase.kt | 12 ++--- .../droidcon_boston/data/UserAgendaRepo.kt | 2 +- .../firebase/DbFirebaseMessagingService.kt | 4 +- .../receivers/NotificationPublisher.kt | 2 +- .../utils/DividerItemDecoration.kt | 4 +- .../utils/ExtensionFunctions.kt | 6 +-- .../utils/NotificationUtils.kt | 46 +++++++++---------- .../utils/RVItemClickListener.kt | 12 ++--- .../droidcon_boston/views/FAQFragment.kt | 4 +- .../droidcon_boston/views/MainActivity.kt | 32 ++++++------- .../views/agenda/AgendaDayFragment.kt | 4 +- .../views/agenda/AgendaDayPagerAdapter.kt | 4 +- .../views/agenda/ScheduleAdapterItem.kt | 12 ++--- .../views/agenda/ScheduleAdapterItemHeader.kt | 2 +- .../views/detail/AgendaDetailFragment.kt | 28 ++++++----- .../views/detail/SpeakerDetailFragment.kt | 14 +++--- .../views/faq/FaqAdapterItem.kt | 4 +- .../views/faq/FaqAdapterItemHeader.kt | 2 +- .../views/social/RVSocialListAdapter.kt | 2 +- .../views/social/SocialFragment.kt | 30 ++++++------ .../views/speaker/SpeakerAdapterItem.kt | 8 ++-- .../views/speaker/SpeakerFragment.kt | 4 +- .../views/volunteer/VolunteerAdapterItem.kt | 8 ++-- .../views/volunteer/VolunteerFragment.kt | 6 +-- 24 files changed, 125 insertions(+), 127 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt index 0e70c02..ff69023 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt @@ -35,16 +35,16 @@ open class FirebaseDatabase { fun getLocalStartTime(): LocalDateTime { return ZonedDateTime.parse(startTime).withZoneSameInstant(ZoneId.systemDefault()) - .toLocalDateTime() + .toLocalDateTime() } fun scheduleNotification(context: Context, eventId: String, sessionDetail: ScheduleRow) { NotificationUtils(context).scheduleNotificationAlarm(getLocalStartTime().minusMinutes( - SESSION_REMINDER_MINUTES_BEFORE), - eventId, - context.getString(R.string.str_session_start_soon, name), - description.getHtmlFormattedSpanned().toString(), - ServiceLocator.gson.toJson(sessionDetail, ScheduleRow::class.java)) + SESSION_REMINDER_MINUTES_BEFORE), + eventId, + context.getString(R.string.str_session_start_soon, name), + description.getHtmlFormattedSpanned().toString(), + ServiceLocator.gson.toJson(sessionDetail, ScheduleRow::class.java)) } fun toScheduleRow(scheduleId: String): ScheduleRow { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt index 5a3c6ad..df2dbaa 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/UserAgendaRepo.kt @@ -9,7 +9,7 @@ class UserAgendaRepo private constructor(context: Context) { private val prefsKey = "UserAgenda" private val sessionIdsKey = "savedSessionsIds" private val sharedPrefs: SharedPreferences = - context.getSharedPreferences(prefsKey, MODE_PRIVATE) + context.getSharedPreferences(prefsKey, MODE_PRIVATE) private val savedSessionIds = HashSet() init { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt index c43f0f5..6104860 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt @@ -33,8 +33,8 @@ class DbFirebaseMessagingService : FirebaseMessagingService() { // Show the notification here val notificationUtils = NotificationUtils(this) notificationUtils.sendAndroidChannelNotification(getString(R.string.conference_name), - bodyStr!!, - 101) + bodyStr!!, + 101) } } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/NotificationPublisher.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/NotificationPublisher.kt index 86fbb63..611f39a 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/NotificationPublisher.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/receivers/NotificationPublisher.kt @@ -10,7 +10,7 @@ class NotificationPublisher : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val notificationManager = - context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notification = intent.getParcelableExtra(NOTIFICATION) val id = intent.getIntExtra(NOTIFICATION_ID, 0) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt index dea6586..b402910 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/DividerItemDecoration.kt @@ -33,7 +33,7 @@ class DividerItemDecoration(context: Context, orientation: Int) : RecyclerView.I val child = parent.getChildAt(i) val params = child.layoutParams as RecyclerView.LayoutParams @Suppress("DEPRECATION") val left = - child.right + params.rightMargin + Math.round(ViewCompat.getTranslationX(child)) + child.right + params.rightMargin + Math.round(ViewCompat.getTranslationX(child)) val right = left + divider!!.intrinsicHeight divider.setBounds(left, top, right, bottom) divider.draw(c!!) @@ -49,7 +49,7 @@ class DividerItemDecoration(context: Context, orientation: Int) : RecyclerView.I val child = parent.getChildAt(i) val params = child.layoutParams as RecyclerView.LayoutParams @Suppress("DEPRECATION") val top = - child.bottom + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child)) + child.bottom + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child)) val bottom = top + divider!!.intrinsicHeight divider.setBounds(left, top, right, bottom) divider.draw(c!!) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt index bd2d074..5b941fd 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt @@ -2,10 +2,10 @@ package com.mentalmachines.droidcon_boston.utils import android.content.Context import android.net.Uri -import androidx.browser.customtabs.CustomTabsIntent -import androidx.core.content.ContextCompat import android.text.Html import android.text.Spanned +import androidx.browser.customtabs.CustomTabsIntent +import androidx.core.content.ContextCompat import com.mentalmachines.droidcon_boston.R @@ -26,6 +26,6 @@ fun String.getHtmlFormattedSpanned(): Spanned { fun Context.loadUriInCustomTab(uriString: String) { val data = Uri.parse(uriString) val customTabsIntent = CustomTabsIntent.Builder() - .setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary)).build() + .setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary)).build() customTabsIntent.launchUrl(this, data) } \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt index 2952257..ae4a7d8 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt @@ -10,9 +10,9 @@ import android.content.pm.PackageManager import android.graphics.Color import android.os.Build import android.os.Build.VERSION_CODES -import androidx.core.app.NotificationCompat import android.text.TextUtils import android.util.Log +import androidx.core.app.NotificationCompat import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError import com.google.firebase.database.ValueEventListener @@ -38,8 +38,8 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // create android channel val androidChannel = NotificationChannel(ANDROID_CHANNEL_ID, - ANDROID_CHANNEL_NAME, - NotificationManager.IMPORTANCE_DEFAULT) + ANDROID_CHANNEL_NAME, + NotificationManager.IMPORTANCE_DEFAULT) // Sets whether notifications posted to this channel should display notification lights androidChannel.enableLights(true) // Sets whether notification posted to this channel should vibrate. @@ -66,11 +66,11 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { val pi = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT) val builder = - NotificationCompat.Builder(applicationContext, channelId).setContentTitle(title) - .setContentText(body).setTicker(getString(R.string.conference_name)) - .setSmallIcon(android.R.drawable.stat_notify_more).setAutoCancel(true) - // for notification click action, also required on Gingerbread and below - .setContentIntent(pi) + NotificationCompat.Builder(applicationContext, channelId).setContentTitle(title) + .setContentText(body).setTicker(getString(R.string.conference_name)) + .setSmallIcon(android.R.drawable.stat_notify_more).setAutoCancel(true) + // for notification click action, also required on Gingerbread and below + .setContentIntent(pi) getNotificationManager().notify(notificationId, builder.build()) } @@ -89,13 +89,13 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { for (roomSnapshot in dataSnapshot.children) { val eventId = roomSnapshot.key ?: "" val scheduleEvent = - roomSnapshot.getValue(FirebaseDatabase.ScheduleEvent::class.java) + roomSnapshot.getValue(FirebaseDatabase.ScheduleEvent::class.java) scheduleEvent?.let { if (userRepo.isSessionBookmarked(eventId) && scheduleEvent.getLocalStartTime().isAfter( - LocalDateTime.now())) { + LocalDateTime.now())) { scheduleEvent.scheduleNotification(context, - eventId, - scheduleEvent.toScheduleRow(eventId)) + eventId, + scheduleEvent.toScheduleRow(eventId)) hasBookmarkedEvents = true } } @@ -120,7 +120,7 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { sessionDetail: String) { if (alarmTime.isAfter(LocalDateTime.now())) { val pendingIntent = - getAgendaSessionNotificationPendingIntent(sessionId, title, body, sessionDetail) + getAgendaSessionNotificationPendingIntent(sessionId, title, body, sessionDetail) val utcInMillis = alarmTime.atZone(ZoneId.systemDefault()).toEpochSecond() * 1000 val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmManager.set(AlarmManager.RTC_WAKEUP, utcInMillis, pendingIntent) @@ -139,8 +139,8 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { val pm = context.packageManager pm.setComponentEnabledSetting(receiver, - if (enabled) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, - PackageManager.DONT_KILL_APP) + if (enabled) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP) } private fun getAgendaSessionNotificationPendingIntent(sessionId: String, @@ -148,16 +148,16 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { body: String = "", sessionDetail: String = ""): PendingIntent { val builder = NotificationCompat.Builder(this, ANDROID_CHANNEL_ID).setContentText(title) - .setStyle(NotificationCompat.BigTextStyle().bigText(body).setBigContentTitle(title)) - .setSmallIcon(R.drawable.ic_notification_session_start).setAutoCancel(true) + .setStyle(NotificationCompat.BigTextStyle().bigText(body).setBigContentTitle(title)) + .setSmallIcon(R.drawable.ic_notification_session_start).setAutoCancel(true) val notificationId = sessionId.hashCode() if (!TextUtils.isEmpty(sessionDetail)) { val sessionIntent = MainActivity.getSessionDetailIntent(this, sessionId, sessionDetail) val contentIntent = PendingIntent.getActivity(this, - notificationId, - sessionIntent, - PendingIntent.FLAG_UPDATE_CURRENT) + notificationId, + sessionIntent, + PendingIntent.FLAG_UPDATE_CURRENT) builder.setContentIntent(contentIntent) } @@ -168,9 +168,9 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { putExtra(NotificationPublisher.NOTIFICATION, builder.build()) } return PendingIntent.getBroadcast(this, - notificationId, - notificationIntent, - PendingIntent.FLAG_UPDATE_CURRENT) + notificationId, + notificationIntent, + PendingIntent.FLAG_UPDATE_CURRENT) } companion object { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt index 508274e..0e79794 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/RVItemClickListener.kt @@ -8,14 +8,14 @@ import androidx.recyclerview.widget.RecyclerView open class RVItemClickListener(context: Context, private val itemClickListener: OnItemClickListener?) : - RecyclerView.OnItemTouchListener { + RecyclerView.OnItemTouchListener { private var gestureDetector: GestureDetector = - GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { - override fun onSingleTapUp(e: MotionEvent): Boolean { - return true - } - }) + GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { + override fun onSingleTapUp(e: MotionEvent): Boolean { + return true + } + }) interface OnItemClickListener { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt index 59c62ae..51ef32f 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/FAQFragment.kt @@ -76,7 +76,7 @@ class FAQFragment : Fragment(), FlexibleAdapter.OnItemClickListener { faqs.forEach { faq -> faq.answers.forEach { answer -> val header: FaqAdapterItemHeader = - questionHeaders[faq.question] ?: FaqAdapterItemHeader(faq.question) + questionHeaders[faq.question] ?: FaqAdapterItemHeader(faq.question) questionHeaders[faq.question] = header val item = FaqAdapterItem(answer, header) @@ -98,7 +98,7 @@ class FAQFragment : Fragment(), FlexibleAdapter.OnItemClickListener { val itemData = item!!.itemData val url = - if (!TextUtils.isEmpty(itemData.otherLink)) itemData.otherLink else itemData.mapLink + if (!TextUtils.isEmpty(itemData.otherLink)) itemData.otherLink else itemData.mapLink val intent = Intent(Intent.ACTION_VIEW) intent.data = Uri.parse(url) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index 82fc0f4..39bc37d 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -42,7 +42,7 @@ class MainActivity : AppCompatActivity() { val sessionDetails = initialIntent.extras?.getString(EXTRA_SESSION_DETAILS) if (!TextUtils.isEmpty(sessionDetails)) { AgendaDetailFragment.addDetailFragmentToStack(supportFragmentManager, - ServiceLocator.gson.fromJson(sessionDetails, ScheduleRow::class.java)) + ServiceLocator.gson.fromJson(sessionDetails, ScheduleRow::class.java)) } else { navView.setCheckedItem(id.nav_agenda) } @@ -84,7 +84,7 @@ class MainActivity : AppCompatActivity() { private fun checkNavMenuItem(title: String) { processMenuItems({ item -> item.title == title }, - { item -> item.setChecked(true).isChecked }) + { item -> item.setChecked(true).isChecked }) } private fun isNavItemChecked(title: String): Boolean { @@ -129,9 +129,9 @@ class MainActivity : AppCompatActivity() { setSupportActionBar(toolbar) actionBarDrawerToggle = ActionBarDrawerToggle(this, - drawer_layout, - R.string.drawer_open, - R.string.drawer_close) + drawer_layout, + R.string.drawer_open, + R.string.drawer_close) drawer_layout.addDrawerListener(actionBarDrawerToggle) navView.setNavigationItemSelectedListener { item -> @@ -217,10 +217,10 @@ class MainActivity : AppCompatActivity() { // Add fragment with tag fragment?.let { supportFragmentManager?.beginTransaction() - // replace in container - ?.replace(R.id.fragment_container, it, title) - // commit fragment transaction - ?.commit() + // replace in container + ?.replace(R.id.fragment_container, it, title) + // commit fragment transaction + ?.commit() } } else { @@ -232,15 +232,15 @@ class MainActivity : AppCompatActivity() { } val fragmentInContainer = - supportFragmentManager?.findFragmentById(R.id.fragment_container) + supportFragmentManager?.findFragmentById(R.id.fragment_container) fragmentInContainer?.let { supportFragmentManager?.beginTransaction() - // detach the fragment that is currently visible - ?.detach(it) - // attach the fragment found as per the tag - ?.attach(it) - // commit fragment transaction - ?.commit() + // detach the fragment that is currently visible + ?.detach(it) + // attach the fragment found as per the tag + ?.attach(it) + // commit fragment transaction + ?.commit() } } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index 259878c..a3ab5ac 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -113,7 +113,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { if (data != null) { val scheduleRow = data.toScheduleRow(key) if (scheduleRow.date == dayFilter && (!onlyMyAgenda || onlyMyAgenda && userAgendaRepo.isSessionBookmarked( - scheduleRow.id))) { + scheduleRow.id))) { rows.add(scheduleRow) } } @@ -146,7 +146,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { } val sortedItems = - items.sortedWith(compareBy { it.itemData.utcStartTimeString }.thenBy { it.roomSortOrder }) + items.sortedWith(compareBy { it.itemData.utcStartTimeString }.thenBy { it.roomSortOrder }) headerAdapter = FlexibleAdapter(sortedItems) headerAdapter!!.addListener(this) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt index 5ce4442..577f86a 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt @@ -6,7 +6,7 @@ import com.mentalmachines.droidcon_boston.data.Schedule class AgendaDayPagerAdapter internal constructor(fm: FragmentManager, private val myAgenda: Boolean) : - FixedFragmentStatePagerAdapter(fm) { + FixedFragmentStatePagerAdapter(fm) { private val PAGE_COUNT = 2 private val tabTitles = arrayOf("Day 1", "Day 2") @@ -17,7 +17,7 @@ class AgendaDayPagerAdapter internal constructor(fm: FragmentManager, override fun getItem(position: Int): Fragment { return AgendaDayFragment.newInstance(myAgenda, - if (position == 0) Schedule.MONDAY else Schedule.TUESDAY) + if (position == 0) Schedule.MONDAY else Schedule.TUESDAY) } override fun getPageTitle(position: Int): CharSequence? { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt index f65a2ed..75f15e3 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt @@ -25,7 +25,7 @@ import java.util.* */ class ScheduleAdapterItem internal constructor(val itemData: Schedule.ScheduleRow, header: ScheduleAdapterItemHeader) : - AbstractSectionableItem(header) { + AbstractSectionableItem(header) { private var startTime: Date = Date() @@ -109,8 +109,8 @@ class ScheduleAdapterItem internal constructor(val itemData: Schedule.ScheduleRo val context = holder.title.context Glide.with(context).load(itemData.photoUrlMap[itemData.primarySpeakerName]) - .transform(CircleTransform(context)).placeholder(R.drawable.emo_im_cool).crossFade() - .into(holder.avatar) + .transform(CircleTransform(context)).placeholder(R.drawable.emo_im_cool).crossFade() + .into(holder.avatar) holder.bookmarkIndicator.visibility = if (userAgendaRepo.isSessionBookmarked(itemData.id)) View.VISIBLE @@ -121,7 +121,7 @@ class ScheduleAdapterItem internal constructor(val itemData: Schedule.ScheduleRo val availableColor = if (itemData.isOver) R.color.colorGray else R.color.colorAccent holder.availableIndicator.setBackgroundColor(ContextCompat.getColor(holder.availableIndicator.context, - availableColor)) + availableColor)) } private fun addBackgroundRipple(holder: ViewHolder) { @@ -162,8 +162,8 @@ class ScheduleAdapterItem internal constructor(val itemData: Schedule.ScheduleRo } constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) : super(view, - adapter, - stickyHeader) { + adapter, + stickyHeader) { findViews(view) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt index a9ebb48..b2b8894 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItemHeader.kt @@ -13,7 +13,7 @@ import eu.davidea.viewholders.FlexibleViewHolder * Sticky header for schedule view */ class ScheduleAdapterItemHeader internal constructor(private val sessionTime: String) : - AbstractHeaderItem() { + AbstractHeaderItem() { override fun equals(other: Any?): Boolean { if (other is ScheduleAdapterItemHeader) { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt index 37888e3..e2d5225 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt @@ -2,10 +2,6 @@ package com.mentalmachines.droidcon_boston.views.detail import android.content.res.ColorStateList import android.os.Bundle -import com.google.android.material.snackbar.Snackbar -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager -import androidx.core.content.ContextCompat import android.text.method.LinkMovementMethod import android.util.Log import android.view.LayoutInflater @@ -13,6 +9,8 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.RelativeLayout +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment import com.bumptech.glide.Glide import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError @@ -56,7 +54,7 @@ class AgendaDetailFragment : Fragment() { super.onViewCreated(view, savedInstanceState) scheduleRowItem = gson.fromJson(arguments!!.getString(Schedule.SCHEDULE_ITEM_ROW), - ScheduleRow::class.java) + ScheduleRow::class.java) fetchDataFromFirebase() populateView() @@ -71,8 +69,8 @@ class AgendaDetailFragment : Fragment() { tv_agenda_detail_room.text = resources.getString(R.string.str_agenda_detail_room, scheduleRowItem.room) tv_agenda_detail_time.text = resources.getString(R.string.str_agenda_detail_time, - scheduleRowItem.startTime, - scheduleRowItem.endTime) + scheduleRowItem.startTime, + scheduleRowItem.endTime) fab_agenda_detail_bookmark.setOnClickListener { @@ -180,23 +178,23 @@ class AgendaDetailFragment : Fragment() { agendaDetailView.addView(tempImg) Glide.with(this).load(itemData.photoUrlMap[speakerName]) - .transform(CircleTransform(tempImg.context)).placeholder(R.drawable.emo_im_cool) - .crossFade().into(tempImg) + .transform(CircleTransform(tempImg.context)).placeholder(R.drawable.emo_im_cool) + .crossFade().into(tempImg) tempImg.setOnClickListener { val eventSpeaker = eventSpeakers[speakerName] val arguments = Bundle() arguments.putString(EventSpeaker.SPEAKER_ITEM_ROW, - gson.toJson(eventSpeaker, EventSpeaker::class.java)) + gson.toJson(eventSpeaker, EventSpeaker::class.java)) val speakerDetailFragment = SpeakerDetailFragment() speakerDetailFragment.arguments = arguments val fragmentManager = activity?.supportFragmentManager fragmentManager?.beginTransaction() - ?.add(R.id.fragment_container, speakerDetailFragment)?.addToBackStack(null) - ?.commit() + ?.add(R.id.fragment_container, speakerDetailFragment)?.addToBackStack(null) + ?.commit() } } tv_agenda_detail_speaker_name.text = speakerNames @@ -219,7 +217,7 @@ class AgendaDetailFragment : Fragment() { val context = fab_agenda_detail_bookmark.context fab_agenda_detail_bookmark.backgroundTintList = if (userAgendaRepo.isSessionBookmarked(scheduleDetail.id)) ColorStateList.valueOf( - ContextCompat.getColor(context, R.color.colorAccent)) + ContextCompat.getColor(context, R.color.colorAccent)) else ColorStateList.valueOf(ContextCompat.getColor(context, R.color.colorLightGray)) } @@ -228,13 +226,13 @@ class AgendaDetailFragment : Fragment() { itemData: Schedule.ScheduleRow) { val arguments = Bundle() arguments.putString(Schedule.SCHEDULE_ITEM_ROW, - gson.toJson(itemData, ScheduleRow::class.java)) + gson.toJson(itemData, ScheduleRow::class.java)) val agendaDetailFragment = AgendaDetailFragment() agendaDetailFragment.arguments = arguments supportFragmentManager.beginTransaction() - .add(R.id.fragment_container, agendaDetailFragment).addToBackStack(null).commit() + .add(R.id.fragment_container, agendaDetailFragment).addToBackStack(null).commit() } } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt index 5d03f72..a088fec 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/SpeakerDetailFragment.kt @@ -32,7 +32,7 @@ class SpeakerDetailFragment : androidx.fragment.app.Fragment() { super.onViewCreated(view, savedInstanceState) val itemData = gson.fromJson(arguments!!.getString(EventSpeaker.SPEAKER_ITEM_ROW), - EventSpeaker::class.java) + EventSpeaker::class.java) populateView(itemData) if (activity is MainActivity) { @@ -53,8 +53,8 @@ class SpeakerDetailFragment : androidx.fragment.app.Fragment() { if (!twitterHandle.isNullOrEmpty()) { imgv_twitter.setOnClickListener { activity?.loadUriInCustomTab(String.format("%s%s", - resources.getString(R.string.twitter_link), - twitterHandle)) + resources.getString(R.string.twitter_link), + twitterHandle)) } } else { imgv_twitter.visibility = View.GONE @@ -65,16 +65,16 @@ class SpeakerDetailFragment : androidx.fragment.app.Fragment() { if (!linkedinHandle.isNullOrEmpty()) { imgv_linkedin.setOnClickListener { activity?.loadUriInCustomTab(String.format("%s%s", - resources.getString(R.string.linkedin_profile_link), - linkedinHandle)) + resources.getString(R.string.linkedin_profile_link), + linkedinHandle)) } } else { imgv_linkedin.visibility = View.GONE } Glide.with(activity).load(itemData.pictureUrl) - .transform(CircleTransform(imgv_speaker_detail_avatar.context)) - .placeholder(R.drawable.emo_im_cool).crossFade().into(imgv_speaker_detail_avatar) + .transform(CircleTransform(imgv_speaker_detail_avatar.context)) + .placeholder(R.drawable.emo_im_cool).crossFade().into(imgv_speaker_detail_avatar) } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt index 5f1307c..8e90803 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt @@ -17,7 +17,7 @@ import eu.davidea.viewholders.FlexibleViewHolder * Used for displaying the FAQ items */ class FaqAdapterItem internal constructor(val itemData: Answer, header: FaqAdapterItemHeader) : - AbstractSectionableItem(header) { + AbstractSectionableItem(header) { override fun equals(other: Any?): Boolean { if (other is FaqAdapterItem) { @@ -49,7 +49,7 @@ class FaqAdapterItem internal constructor(val itemData: Answer, header: FaqAdapt if (!TextUtils.isEmpty(itemData.photoLink)) { val context = holder.faq_text.context Glide.with(context).load(itemData.photoLink).crossFade().centerCrop() - .into(holder.faq_photo) + .into(holder.faq_photo) holder.faq_photo.visibility = View.VISIBLE } else { holder.faq_photo.visibility = View.GONE diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt index 8840b77..9015495 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItemHeader.kt @@ -13,7 +13,7 @@ import eu.davidea.viewholders.FlexibleViewHolder * Header for FAQ view */ class FaqAdapterItemHeader internal constructor(private val question: String) : - AbstractHeaderItem() { + AbstractHeaderItem() { override fun equals(other: Any?): Boolean { if (other is FaqAdapterItemHeader) { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt index 940c7cb..89da5f3 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/RVSocialListAdapter.kt @@ -12,7 +12,7 @@ import com.mentalmachines.droidcon_boston.modal.SocialModal import java.util.* internal class RVSocialListAdapter(private var socialList: ArrayList) : - Adapter() { + Adapter() { inner class ListViewHolder(itemView: View) : ViewHolder(itemView) { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt index 4b21e93..1428747 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/social/SocialFragment.kt @@ -43,29 +43,29 @@ class SocialFragment : Fragment() { // Set On Click social_rv.addOnItemTouchListener(RVItemClickListener(context!!, - object : OnItemClickListener { - override fun onItemClick(view: View, position: Int) { - context?.loadUriInCustomTab(socialList[position].link.toString()) - } - })) + object : OnItemClickListener { + override fun onItemClick(view: View, position: Int) { + context?.loadUriInCustomTab(socialList[position].link.toString()) + } + })) } private fun prepareSocialList(): ArrayList { val socialList = ArrayList() socialList.add(SocialModal(R.drawable.social_facebook, - getString(R.string.social_title_facebook), - getString(R.string.facebook_link))) + getString(R.string.social_title_facebook), + getString(R.string.facebook_link))) socialList.add(SocialModal(R.drawable.social_instagram, - getString(R.string.social_title_instagram), - getString(R.string.instagram_link))) + getString(R.string.social_title_instagram), + getString(R.string.instagram_link))) socialList.add(SocialModal(R.drawable.social_linkedin, - getString(R.string.social_title_linkedin), - getString(R.string.linkedin_link))) + getString(R.string.social_title_linkedin), + getString(R.string.linkedin_link))) socialList.add(SocialModal(R.drawable.social_twitter, - getString(R.string.social_title_twitter), - String.format("%s%s", - resources.getString(R.string.twitter_link), - getString(string.droidconbos_twitter_handle)))) + getString(R.string.social_title_twitter), + String.format("%s%s", + resources.getString(R.string.twitter_link), + getString(string.droidconbos_twitter_handle)))) return socialList } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt index a437b46..076d0e2 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerAdapterItem.kt @@ -18,7 +18,7 @@ import eu.davidea.viewholders.FlexibleViewHolder * Used for displaying speaker list items on the all speakers "Speakers" page. */ class SpeakerAdapterItem internal constructor(val itemData: EventSpeaker) : - AbstractFlexibleItem() { + AbstractFlexibleItem() { override fun bindViewHolder(adapter: FlexibleAdapter>?, holder: ViewHolder, @@ -31,7 +31,7 @@ class SpeakerAdapterItem internal constructor(val itemData: EventSpeaker) : val context = holder.name.context Glide.with(context).load(itemData.pictureUrl).transform(CircleTransform(context)) - .placeholder(R.drawable.emo_im_cool).crossFade().into(holder.avatar) + .placeholder(R.drawable.emo_im_cool).crossFade().into(holder.avatar) } override fun equals(other: Any?): Boolean { @@ -68,8 +68,8 @@ class SpeakerAdapterItem internal constructor(val itemData: EventSpeaker) : } constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) : super(view, - adapter, - stickyHeader) { + adapter, + stickyHeader) { findViews(view) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt index 6e5e242..477aed7 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/speaker/SpeakerFragment.kt @@ -74,14 +74,14 @@ class SpeakerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { val arguments = Bundle() arguments.putString(EventSpeaker.SPEAKER_ITEM_ROW, - gson.toJson(itemData, EventSpeaker::class.java)) + gson.toJson(itemData, EventSpeaker::class.java)) val speakerDetailFragment = SpeakerDetailFragment() speakerDetailFragment.arguments = arguments val fragmentManager = activity?.supportFragmentManager fragmentManager?.beginTransaction()?.add(R.id.fragment_container, speakerDetailFragment) - ?.addToBackStack(null)?.commit() + ?.addToBackStack(null)?.commit() } return true diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt index 1d34478..cc67df7 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerAdapterItem.kt @@ -18,7 +18,7 @@ import eu.davidea.viewholders.FlexibleViewHolder * Used for displaying volunteer list items on the all volunteers "volunteers" page. */ class VolunteerAdapterItem internal constructor(val itemData: VolunteerEvent) : - AbstractFlexibleItem() { + AbstractFlexibleItem() { override fun bindViewHolder(adapter: FlexibleAdapter>?, holder: ViewHolder, @@ -37,7 +37,7 @@ class VolunteerAdapterItem internal constructor(val itemData: VolunteerEvent) : val context = holder.name.context Glide.with(context).load(itemData.pictureUrl).transform(CircleTransform(context)) - .placeholder(R.drawable.emo_im_cool).crossFade().into(holder.avatar) + .placeholder(R.drawable.emo_im_cool).crossFade().into(holder.avatar) } override fun equals(other: Any?): Boolean { @@ -74,8 +74,8 @@ class VolunteerAdapterItem internal constructor(val itemData: VolunteerEvent) : } constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) : super(view, - adapter, - stickyHeader) { + adapter, + stickyHeader) { findViews(view) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt index 511f99f..d45c2c8 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/volunteer/VolunteerFragment.kt @@ -63,7 +63,7 @@ class VolunteerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private fun fetchDataFromFirebase() { firebaseHelper.volunteerDatabase.orderByChild("firstName") - .addValueEventListener(dataListener) + .addValueEventListener(dataListener) } override fun onItemClick(view: View, position: Int): Boolean { @@ -71,8 +71,8 @@ class VolunteerFragment : Fragment(), FlexibleAdapter.OnItemClickListener { if (item is VolunteerAdapterItem && !item.itemData.twitter.isEmpty()) { val context = activity as Context context.loadUriInCustomTab(String.format("%s%s", - resources.getString(R.string.twitter_link), - item.itemData.twitter)) + resources.getString(R.string.twitter_link), + item.itemData.twitter)) return false } From 3effa657520d26216ada771687a9fc24bc712ae3 Mon Sep 17 00:00:00 2001 From: Nishant Srivastava Date: Sun, 18 Nov 2018 10:37:26 +0100 Subject: [PATCH 009/173] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20upgrade=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Droidcon-Boston/app/build.gradle | 6 +++--- Droidcon-Boston/build.gradle | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index 9b94c68..cb836f9 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -60,7 +60,7 @@ dependencies { // Support final support = '1.0.0' - implementation "androidx.appcompat:appcompat:1.0.1" + implementation "androidx.appcompat:appcompat:1.0.2" implementation "androidx.legacy:legacy-support-v4:$support" implementation "androidx.cardview:cardview:$support" implementation "com.google.android.material:material:$support" @@ -68,8 +68,8 @@ dependencies { // Firebase implementation "com.google.firebase:firebase-messaging:17.3.4" - implementation "com.google.firebase:firebase-database:16.0.4" - implementation "com.google.firebase:firebase-core:16.0.4" + implementation "com.google.firebase:firebase-database:16.0.5" + implementation "com.google.firebase:firebase-core:16.0.5" // Crashlytics only for release builds releaseImplementation('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') { diff --git a/Droidcon-Boston/build.gradle b/Droidcon-Boston/build.gradle index b556fe4..90fd6e3 100644 --- a/Droidcon-Boston/build.gradle +++ b/Droidcon-Boston/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.0' + ext.kotlin_version = '1.3.10' repositories { google() jcenter() From e59701c744759a6a32a65edb873e50fd8638d477 Mon Sep 17 00:00:00 2001 From: Nishant Srivastava Date: Mon, 19 Nov 2018 21:04:56 +0100 Subject: [PATCH 010/173] =?UTF-8?q?=F0=9F=91=8C=20Updating=20code=20due=20?= =?UTF-8?q?to=20code=20review=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Droidcon-Boston/app/build.gradle | 49 +++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index cb836f9..79b2690 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -55,37 +55,54 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) + //region Version + final junit = "4.12" + final support = '1.0.0' + final appCompat = '1.0.2' + final firebaseDatabase = '16.0.5' + final firebaseCore = '16.0.5' + final firebaseMessaging = '17.3.4' + final crashlytics = '2.9.1' + final gson = '2.8.2' + final flexibleAdapter = '5.0.1' + final flexibleAdapterUi = '1.0.0-b3' + final glide = '3.7.0' + final threeTenAbp = '1.0.5' + final recyclerRefreshLayout = '2.0.5' + //endregion + + //region Dependencies + // Kotlin + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + // TESTING - testImplementation "junit:junit:4.12" + testImplementation "junit:junit:$junit" // Support - final support = '1.0.0' - implementation "androidx.appcompat:appcompat:1.0.2" + implementation "androidx.appcompat:appcompat:$appCompat" implementation "androidx.legacy:legacy-support-v4:$support" implementation "androidx.cardview:cardview:$support" implementation "com.google.android.material:material:$support" implementation "androidx.browser:browser:$support" // Firebase - implementation "com.google.firebase:firebase-messaging:17.3.4" - implementation "com.google.firebase:firebase-database:16.0.5" - implementation "com.google.firebase:firebase-core:16.0.5" + implementation "com.google.firebase:firebase-messaging:$firebaseMessaging" + implementation "com.google.firebase:firebase-database:$firebaseDatabase" + implementation "com.google.firebase:firebase-core:$firebaseCore" // Crashlytics only for release builds - releaseImplementation('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') { + releaseImplementation("com.crashlytics.sdk.android:crashlytics:$crashlytics@aar") { transitive = true } // Misc - implementation 'com.google.code.gson:gson:2.8.2' - implementation 'eu.davidea:flexible-adapter:5.0.1' - implementation 'eu.davidea:flexible-adapter-ui:1.0.0-b3' - implementation 'com.github.bumptech.glide:glide:3.7.0' - implementation 'com.jakewharton.threetenabp:threetenabp:1.0.5' - implementation 'com.dinuscxj:recyclerrefreshlayout:2.0.5' - - // Kotlin - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "com.google.code.gson:gson:$gson" + implementation "eu.davidea:flexible-adapter:$flexibleAdapter" + implementation "eu.davidea:flexible-adapter-ui:$flexibleAdapterUi" + implementation "com.github.bumptech.glide:glide:$glide" + implementation "com.jakewharton.threetenabp:threetenabp:$threeTenAbp" + implementation "com.dinuscxj:recyclerrefreshlayout:$recyclerRefreshLayout" + //endregion } apply plugin: 'com.google.gms.google-services' \ No newline at end of file From fbe442eaf737c09404693826d12b6808605e8a46 Mon Sep 17 00:00:00 2001 From: Nishant Srivastava Date: Mon, 19 Nov 2018 21:10:50 +0100 Subject: [PATCH 011/173] =?UTF-8?q?=F0=9F=8E=A8=20structure/format:=20swit?= =?UTF-8?q?ched=20to=20official=20kotlin=20code=20style?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Droidcon-Boston/.idea/codeStyles/Project.xml | 6 ++ .../droidcon_boston/data/FirebaseDatabase.kt | 87 +++++++++------- .../droidcon_boston/data/Schedule.kt | 32 +++--- .../droidcon_boston/data/UserAgendaRepo.kt | 2 +- .../firebase/DbFirebaseMessagingService.kt | 8 +- .../receivers/NotificationPublisher.kt | 2 +- .../utils/DividerItemDecoration.kt | 4 +- .../utils/ExtensionFunctions.kt | 2 +- .../utils/NotificationUtils.kt | 98 +++++++++++-------- .../utils/RVItemClickListener.kt | 18 ++-- .../droidcon_boston/views/AboutFragment.kt | 8 +- .../droidcon_boston/views/CocFragment.kt | 8 +- .../droidcon_boston/views/FAQFragment.kt | 12 ++- .../droidcon_boston/views/MainActivity.kt | 59 ++++++----- .../views/agenda/AgendaDayFragment.kt | 14 ++- .../views/agenda/AgendaDayPagerAdapter.kt | 14 ++- .../views/agenda/AgendaFragment.kt | 8 +- .../views/agenda/ScheduleAdapterItem.kt | 44 ++++++--- .../views/agenda/ScheduleAdapterItemHeader.kt | 26 +++-- .../views/detail/AgendaDetailFragment.kt | 61 +++++++----- .../views/detail/SpeakerDetailFragment.kt | 34 ++++--- .../views/faq/FaqAdapterItem.kt | 20 ++-- .../views/faq/FaqAdapterItemHeader.kt | 26 +++-- .../views/social/RVSocialListAdapter.kt | 2 +- .../views/social/SocialFragment.kt | 59 ++++++++--- .../views/speaker/SpeakerAdapterItem.kt | 28 +++--- .../views/speaker/SpeakerFragment.kt | 16 +-- .../views/transform/CircleTransform.kt | 10 +- .../views/volunteer/VolunteerAdapterItem.kt | 28 +++--- .../views/volunteer/VolunteerFragment.kt | 18 ++-- 30 files changed, 464 insertions(+), 290 deletions(-) diff --git a/Droidcon-Boston/.idea/codeStyles/Project.xml b/Droidcon-Boston/.idea/codeStyles/Project.xml index f874795..15a37d4 100644 --- a/Droidcon-Boston/.idea/codeStyles/Project.xml +++ b/Droidcon-Boston/.idea/codeStyles/Project.xml @@ -34,6 +34,9 @@ + + diff --git a/Droidcon-Boston/app/src/main/res/layout/speaker_item.xml b/Droidcon-Boston/app/src/main/res/layout/speaker_item.xml index 3ee23fb..b032585 100644 --- a/Droidcon-Boston/app/src/main/res/layout/speaker_item.xml +++ b/Droidcon-Boston/app/src/main/res/layout/speaker_item.xml @@ -8,7 +8,7 @@ android:orientation="horizontal" tools:ignore="RtlSymmetry"> - diff --git a/Droidcon-Boston/app/src/main/res/layout/volunteer_item.xml b/Droidcon-Boston/app/src/main/res/layout/volunteer_item.xml index 2db96a8..a44d202 100644 --- a/Droidcon-Boston/app/src/main/res/layout/volunteer_item.xml +++ b/Droidcon-Boston/app/src/main/res/layout/volunteer_item.xml @@ -8,7 +8,7 @@ android:orientation="horizontal" tools:ignore="RtlSymmetry"> - diff --git a/Droidcon-Boston/app/src/main/res/values/strings.xml b/Droidcon-Boston/app/src/main/res/values/strings.xml index 229a055..25581ae 100644 --- a/Droidcon-Boston/app/src/main/res/values/strings.xml +++ b/Droidcon-Boston/app/src/main/res/values/strings.xml @@ -43,4 +43,11 @@ Close droidconbos No talks added to My Schedule\nfor this day + Navigation Header + Logo + header Background + Navigation Header Image + Social Icon + LinkedIn Icon + Twitter Icon From 6701fbeadd6dae0b76b6163a9af736c44c66c949 Mon Sep 17 00:00:00 2001 From: AdamMc331 Date: Sun, 30 Dec 2018 11:42:56 -0500 Subject: [PATCH 013/173] Capitalized string resource. --- Droidcon-Boston/app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Droidcon-Boston/app/src/main/res/values/strings.xml b/Droidcon-Boston/app/src/main/res/values/strings.xml index 25581ae..73feba4 100644 --- a/Droidcon-Boston/app/src/main/res/values/strings.xml +++ b/Droidcon-Boston/app/src/main/res/values/strings.xml @@ -45,7 +45,7 @@ No talks added to My Schedule\nfor this day Navigation Header Logo - header Background + Header Background Navigation Header Image Social Icon LinkedIn Icon From b50a952a6675c3b2c7bf8430dceeb12ab358b26a Mon Sep 17 00:00:00 2001 From: Ken Yee Date: Sun, 13 Jan 2019 20:27:47 -0500 Subject: [PATCH 014/173] initial Firebase auth hookup --- Droidcon-Boston/app/build.gradle | 5 +- .../droidcon_boston/views/MainActivity.kt | 97 ++++++++++++++++--- .../app/src/main/res/menu/nav_menu.xml | 4 + .../app/src/main/res/values/strings.xml | 3 + Droidcon-Boston/build.gradle | 2 +- 5 files changed, 95 insertions(+), 16 deletions(-) diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index 79b2690..fd40519 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -60,7 +60,7 @@ dependencies { final support = '1.0.0' final appCompat = '1.0.2' final firebaseDatabase = '16.0.5' - final firebaseCore = '16.0.5' + final firebaseCore = '16.0.6' final firebaseMessaging = '17.3.4' final crashlytics = '2.9.1' final gson = '2.8.2' @@ -90,6 +90,9 @@ dependencies { implementation "com.google.firebase:firebase-database:$firebaseDatabase" implementation "com.google.firebase:firebase-core:$firebaseCore" + implementation 'com.firebaseui:firebase-ui-auth:4.3.1' + implementation 'com.twitter.sdk.android:twitter-core:3.3.0' + // Crashlytics only for release builds releaseImplementation("com.crashlytics.sdk.android:crashlytics:$crashlytics@aar") { transitive = true diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index 72b6d20..157b801 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -1,5 +1,7 @@ package com.mentalmachines.droidcon_boston.views +import android.app.Activity +import android.app.AlertDialog import android.content.Context import android.content.Intent import android.content.res.Configuration @@ -10,6 +12,11 @@ import android.view.MenuItem import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AppCompatActivity import androidx.core.view.GravityCompat +import androidx.fragment.app.FragmentManager +import com.firebase.ui.auth.AuthUI +import com.firebase.ui.auth.IdpResponse +import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.auth.FirebaseUser import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.R.id import com.mentalmachines.droidcon_boston.R.string @@ -26,6 +33,7 @@ import kotlinx.android.synthetic.main.main_activity.* class MainActivity : AppCompatActivity() { private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle + private var user: FirebaseUser? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -45,6 +53,7 @@ class MainActivity : AppCompatActivity() { supportFragmentManager, ServiceLocator.gson.fromJson(sessionDetails, ScheduleRow::class.java) ) + updateSelectedNavItem(supportFragmentManager) } else { navView.setCheckedItem(id.nav_agenda) } @@ -63,30 +72,35 @@ class MainActivity : AppCompatActivity() { // If drawer is open if (drawer_layout.isDrawerOpen(GravityCompat.START)) { // close the drawer - drawer_layout.closeDrawer(Gravity.START) + drawer_layout.closeDrawer(GravityCompat.START) } else { super.onBackPressed() val manager = supportFragmentManager if (manager.backStackEntryCount == 0) { // special handling where user clicks on back button in a detail fragment - val currentFragment = manager.findFragmentById(R.id.fragment_container) - if (currentFragment is AgendaFragment) { - if (currentFragment.isMyAgenda()) { - checkNavMenuItem(getString(R.string.str_my_schedule)) - } else { - checkNavMenuItem(getString(R.string.str_agenda)) - } - } else if (currentFragment is SpeakerFragment) { - checkNavMenuItem(getString(R.string.str_speakers)) - } + updateSelectedNavItem(manager) } } } + private fun updateSelectedNavItem(manager: FragmentManager) { + val currentFragment = manager.findFragmentById(id.fragment_container) + if (currentFragment is AgendaFragment) { + if (currentFragment.isMyAgenda()) { + checkNavMenuItem(getString(string.str_my_schedule)) + } else { + checkNavMenuItem(getString(string.str_agenda)) + } + } else if (currentFragment is SpeakerFragment) { + checkNavMenuItem(getString(string.str_speakers)) + } + } + private fun checkNavMenuItem(title: String) { processMenuItems({ item -> item.title == title }, - { item -> item.setChecked(true).isChecked }) + { item -> item.setChecked(true).isChecked }, + processAll = true) } private fun isNavItemChecked(title: String): Boolean { @@ -122,9 +136,11 @@ class MainActivity : AppCompatActivity() { if (!processAll) { return result } + } else { + item.isChecked = false } } - return false + return processAll } @@ -162,9 +178,20 @@ class MainActivity : AppCompatActivity() { R.id.nav_about -> replaceFragment(getString(R.string.str_about_us)) R.id.nav_speakers -> replaceFragment(getString(R.string.str_speakers)) R.id.nav_volunteers -> replaceFragment(getString(R.string.str_volunteers)) + R.id.nav_login_logout -> { + if (user != null) { + logout() + } else { + login() + } + } } - navView.setCheckedItem(item.itemId) + if (item.itemId != R.id.nav_login_logout) { + navView.setCheckedItem(item.itemId) + } else { + updateSelectedNavItem(supportFragmentManager) + } true } @@ -264,10 +291,52 @@ class MainActivity : AppCompatActivity() { } } + fun login() { + val providers = arrayListOf( + AuthUI.IdpConfig.GoogleBuilder().build()) + + startActivityForResult( + AuthUI.getInstance() + .createSignInIntentBuilder() + .setAvailableProviders(providers) + .setLogo(R.mipmap.ic_launcher) + .build(), + RC_SIGN_IN) + } + + fun logout() { + AuthUI.getInstance() + .signOut(this) + user = null + navView.menu.findItem(R.id.nav_login_logout).title = getString(R.string.str_login) + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + + if (requestCode == RC_SIGN_IN) { + val response = IdpResponse.fromResultIntent(data) + + if (resultCode == Activity.RESULT_OK) { + user = FirebaseAuth.getInstance().currentUser + navView.menu.findItem(R.id.nav_login_logout).title = getString(R.string.str_logout) + } else { + response?.let { + AlertDialog.Builder(this) + .setTitle(R.string.str_title_error) + .setMessage(it.error?.message) + .show() + } + } + } + } + companion object { private const val EXTRA_SESSIONID = "MainActivity.EXTRA_SESSIONID" private const val EXTRA_SESSION_DETAILS = "MainActivity.EXTRA_SESSION_DETAILS" + private const val RC_SIGN_IN = 1 + fun getSessionDetailIntent( context: Context, sessionId: String, diff --git a/Droidcon-Boston/app/src/main/res/menu/nav_menu.xml b/Droidcon-Boston/app/src/main/res/menu/nav_menu.xml index 1be5fb1..046b39f 100644 --- a/Droidcon-Boston/app/src/main/res/menu/nav_menu.xml +++ b/Droidcon-Boston/app/src/main/res/menu/nav_menu.xml @@ -37,6 +37,10 @@ android:id="@+id/nav_about" android:icon="@drawable/ic_aboutus" android:title="@string/str_about_us" /> + + diff --git a/Droidcon-Boston/app/src/main/res/values/strings.xml b/Droidcon-Boston/app/src/main/res/values/strings.xml index 73feba4..03042f4 100644 --- a/Droidcon-Boston/app/src/main/res/values/strings.xml +++ b/Droidcon-Boston/app/src/main/res/values/strings.xml @@ -26,6 +26,9 @@ Speakers Volunteers Code Of Conduct + Log In + Log Out + Error Facebook Instagram LinkedIn diff --git a/Droidcon-Boston/build.gradle b/Droidcon-Boston/build.gradle index 90fd6e3..3a53e82 100644 --- a/Droidcon-Boston/build.gradle +++ b/Droidcon-Boston/build.gradle @@ -10,7 +10,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0-beta02' + classpath 'com.android.tools.build:gradle:3.3.0-rc03' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From 80190dda727d7220ece26c1b0a8a616d4f200344 Mon Sep 17 00:00:00 2001 From: Ken Yee Date: Wed, 16 Jan 2019 21:37:43 -0500 Subject: [PATCH 015/173] refactor out an auth controller class --- .../firebase/AuthController.kt | 53 ++++++++++++ .../droidcon_boston/views/MainActivity.kt | 85 +++++++------------ Droidcon-Boston/build.gradle | 2 +- 3 files changed, 87 insertions(+), 53 deletions(-) create mode 100644 Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/AuthController.kt diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/AuthController.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/AuthController.kt new file mode 100644 index 0000000..d518dab --- /dev/null +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/AuthController.kt @@ -0,0 +1,53 @@ +package com.mentalmachines.droidcon_boston.firebase + +import android.app.Activity +import android.content.Context +import android.content.Intent +import androidx.annotation.DrawableRes +import androidx.appcompat.app.AppCompatActivity +import com.firebase.ui.auth.AuthUI +import com.firebase.ui.auth.IdpResponse +import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.auth.FirebaseUser + +class AuthController(@DrawableRes private val loginScreenAppIcon: Int) { + private var user: FirebaseUser? = null + + val isLoggedIn: Boolean + get() = (user != null) + + fun login(activity: AppCompatActivity, resultCode: Int) { + + val providers = arrayListOf( + AuthUI.IdpConfig.GoogleBuilder().build()) + + activity.startActivityForResult( + AuthUI.getInstance() + .createSignInIntentBuilder() + .setAvailableProviders(providers) + .setLogo(loginScreenAppIcon) + .build(), + resultCode) + } + + /*** + * Returns an error message if there was a login error + * or null if successful + */ + fun handleLoginResult(resultCode: Int, data: Intent?): String? { + val response = IdpResponse.fromResultIntent(data) + + return if (resultCode == Activity.RESULT_OK) { + user = FirebaseAuth.getInstance().currentUser + null + } else { + response?.error?.message + } + } + + fun logout(context: Context) { + AuthUI.getInstance() + .signOut(context) + user = null + } +} diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index 157b801..481d74f 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -1,26 +1,21 @@ package com.mentalmachines.droidcon_boston.views -import android.app.Activity import android.app.AlertDialog import android.content.Context import android.content.Intent import android.content.res.Configuration import android.os.Bundle import android.text.TextUtils -import android.view.Gravity import android.view.MenuItem import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AppCompatActivity import androidx.core.view.GravityCompat import androidx.fragment.app.FragmentManager -import com.firebase.ui.auth.AuthUI -import com.firebase.ui.auth.IdpResponse -import com.google.firebase.auth.FirebaseAuth -import com.google.firebase.auth.FirebaseUser import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.R.id import com.mentalmachines.droidcon_boston.R.string import com.mentalmachines.droidcon_boston.data.Schedule.ScheduleRow +import com.mentalmachines.droidcon_boston.firebase.AuthController import com.mentalmachines.droidcon_boston.utils.ServiceLocator import com.mentalmachines.droidcon_boston.views.agenda.AgendaFragment import com.mentalmachines.droidcon_boston.views.detail.AgendaDetailFragment @@ -33,12 +28,14 @@ import kotlinx.android.synthetic.main.main_activity.* class MainActivity : AppCompatActivity() { private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle - private var user: FirebaseUser? = null + private lateinit var authController: AuthController override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main_activity) + authController = AuthController(R.mipmap.ic_launcher) + initNavDrawerToggle() initFragmentsFromIntent(intent) @@ -119,25 +116,27 @@ class MainActivity : AppCompatActivity() { val menu = navView.menu for (i in 0 until menu.size()) { val item = menu.getItem(i) - if (item.hasSubMenu()) { - val subMenu = item.subMenu - for (j in 0 until subMenu.size()) { - val subMenuItem = subMenu.getItem(j) - - if (titleMatcher(subMenuItem)) { - val result = matchFunc(subMenuItem) - if (!processAll) { - return result + when { + item.hasSubMenu() -> { + val subMenu = item.subMenu + for (j in 0 until subMenu.size()) { + val subMenuItem = subMenu.getItem(j) + + if (titleMatcher(subMenuItem)) { + val result = matchFunc(subMenuItem) + if (!processAll) { + return result + } } } } - } else if (titleMatcher(item)) { - val result = matchFunc(item) - if (!processAll) { - return result + titleMatcher(item) -> { + val result = matchFunc(item) + if (!processAll) { + return result + } } - } else { - item.isChecked = false + else -> item.isChecked = false } } return processAll @@ -179,7 +178,7 @@ class MainActivity : AppCompatActivity() { R.id.nav_speakers -> replaceFragment(getString(R.string.str_speakers)) R.id.nav_volunteers -> replaceFragment(getString(R.string.str_volunteers)) R.id.nav_login_logout -> { - if (user != null) { + if (authController.isLoggedIn) { logout() } else { login() @@ -291,43 +290,25 @@ class MainActivity : AppCompatActivity() { } } - fun login() { - val providers = arrayListOf( - AuthUI.IdpConfig.GoogleBuilder().build()) - - startActivityForResult( - AuthUI.getInstance() - .createSignInIntentBuilder() - .setAvailableProviders(providers) - .setLogo(R.mipmap.ic_launcher) - .build(), - RC_SIGN_IN) + private fun login() { + authController.login(this, RC_SIGN_IN) } - fun logout() { - AuthUI.getInstance() - .signOut(this) - user = null + private fun logout() { + authController.logout(this) navView.menu.findItem(R.id.nav_login_logout).title = getString(R.string.str_login) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (requestCode == RC_SIGN_IN) { - val response = IdpResponse.fromResultIntent(data) - - if (resultCode == Activity.RESULT_OK) { - user = FirebaseAuth.getInstance().currentUser - navView.menu.findItem(R.id.nav_login_logout).title = getString(R.string.str_logout) - } else { - response?.let { - AlertDialog.Builder(this) - .setTitle(R.string.str_title_error) - .setMessage(it.error?.message) - .show() - } - } + authController.handleLoginResult(resultCode, data)?.let { + AlertDialog.Builder(this) + .setTitle(R.string.str_title_error) + .setMessage(it) + .show() + } ?: run { + navView.menu.findItem(R.id.nav_login_logout).title = getString(R.string.str_logout) } } diff --git a/Droidcon-Boston/build.gradle b/Droidcon-Boston/build.gradle index 3a53e82..80bcc58 100644 --- a/Droidcon-Boston/build.gradle +++ b/Droidcon-Boston/build.gradle @@ -10,7 +10,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0-rc03' + classpath 'com.android.tools.build:gradle:3.3.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From d67aae9d784c17af4eb627f524f1cf6a839e934e Mon Sep 17 00:00:00 2001 From: n8ebel Date: Fri, 18 Jan 2019 14:59:02 -0800 Subject: [PATCH 016/173] dependencies: udpate plugin dependencies Update gradle & kotlin plugin dependencies after migration to Android Studio 3.3 --- Droidcon-Boston/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Droidcon-Boston/build.gradle b/Droidcon-Boston/build.gradle index 90fd6e3..a882695 100644 --- a/Droidcon-Boston/build.gradle +++ b/Droidcon-Boston/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.10' + ext.kotlin_version = '1.3.11' repositories { google() jcenter() @@ -10,7 +10,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0-beta02' + classpath 'com.android.tools.build:gradle:3.3.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From 321cbe233ce282a33322cfb1747aedc44b531c0a Mon Sep 17 00:00:00 2001 From: n8ebel Date: Sat, 19 Jan 2019 10:27:31 -0800 Subject: [PATCH 017/173] build: add initial CircleCi config file the config file must live at the current path in the root level directory the file is largely the same as the default but with updated permissions and paths for our non-standard repo structure --- .circleci/config.yml | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..ae1fec5 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,38 @@ +version: 2 +jobs: + build: + docker: + - image: circleci/android:api-28-alpha + + environment: + JVM_OPTS: -Xmx3200m + + steps: + - checkout: + + - restore_cache: + key: jars-{{ checksum "Droidcon-Boston/build.gradle" }}-{{ checksum "Droidcon-Boston/app/build.gradle" }} + + - run: + name: Chmod permissions #if permission for Gradlew Dependencies fail, use this. + command: cd Droidcon-Boston && pwd && ls && sudo chmod +x ./gradlew + + - run: + name: Download Dependencies + command: cd Droidcon-Boston && ./gradlew androidDependencies + + - save_cache: + paths: + - .gradle + key: jars-{{ checksum "Droidcon-Boston/build.gradle" }}-{{ checksum "Droidcon-Boston/app/build.gradle" }} + + - run: + name: Run Tests + command: cd Droidcon-Boston && ./gradlew lint test + + - store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/ + path: app/build/reports + destination: reports + + - store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/ + path: app/build/test-results \ No newline at end of file From 17eb3e543b30c6ca3073319bec799c47214cbab4 Mon Sep 17 00:00:00 2001 From: n8ebel Date: Sat, 19 Jan 2019 10:43:39 -0800 Subject: [PATCH 018/173] build: update circle config artifact paths This should allow the build artifacts to be properly stored in the circleci output --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ae1fec5..1a5b060 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,8 +31,8 @@ jobs: command: cd Droidcon-Boston && ./gradlew lint test - store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/ - path: app/build/reports + path: Droidcon-Boston/app/build/reports destination: reports - store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/ - path: app/build/test-results \ No newline at end of file + path: Droidcon-Boston/app/build/test-results \ No newline at end of file From ee1fb4c11e983d5671984fa273eb094f61cc3b46 Mon Sep 17 00:00:00 2001 From: n8ebel Date: Sat, 19 Jan 2019 11:22:47 -0800 Subject: [PATCH 019/173] build: integrate static analysis plugins add ktlint, detekt plugins add the nvoda static analysis plugin to help make configuration easier --- Droidcon-Boston/app/build.gradle | 30 ++ Droidcon-Boston/build.gradle | 11 +- Droidcon-Boston/team-props/detekt-config.yml | 345 +++++++++++++++++++ Droidcon-Boston/team-props/lint-config.xml | 4 + 4 files changed, 389 insertions(+), 1 deletion(-) create mode 100644 Droidcon-Boston/team-props/detekt-config.yml create mode 100644 Droidcon-Boston/team-props/lint-config.xml diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index 79b2690..cbc48ba 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -1,7 +1,12 @@ +import org.jlleitschuh.gradle.ktlint.reporter.ReporterType + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'io.fabric' +apply plugin: 'com.novoda.static-analysis' +apply plugin: "io.gitlab.arturbosch.detekt" +apply plugin: "org.jlleitschuh.gradle.ktlint" android { compileSdkVersion 28 @@ -52,6 +57,31 @@ android { } } +staticAnalysis { + penalty { + maxErrors = 0 + maxWarnings = 0 + } + + lintOptions { + lintConfig rootProject.file('team-props/lint-config.xml') + checkReleaseBuilds false + warningsAsErrors true + } + + detekt { + config = rootProject.files('team-props/detekt-config.yml') + filters = '.*test.*,.*/resources/.*,.*/tmp/.*' + } + + ktlint { + android true + reporters = [ReporterType.CHECKSTYLE] + + includeVariants { variant -> variant.name.contains('debug') } + } +} + dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) diff --git a/Droidcon-Boston/build.gradle b/Droidcon-Boston/build.gradle index a882695..d60880c 100644 --- a/Droidcon-Boston/build.gradle +++ b/Droidcon-Boston/build.gradle @@ -8,6 +8,10 @@ buildscript { maven { url 'https://maven.fabric.io/public' } + + maven { + url "https://plugins.gradle.org/m2/" + } } dependencies { classpath 'com.android.tools.build:gradle:3.3.0' @@ -17,7 +21,12 @@ buildscript { classpath 'com.google.gms:google-services:4.0.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'io.fabric.tools:gradle:1.25.4' + classpath 'io.fabric.tools:gradle:1.25.4'\ + + // static analysis plugins + classpath 'com.novoda:gradle-static-analysis-plugin:0.8' + classpath 'io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.0.0-RC12' + classpath 'gradle.plugin.org.jlleitschuh.gradle:ktlint-gradle:5.1.0' } } diff --git a/Droidcon-Boston/team-props/detekt-config.yml b/Droidcon-Boston/team-props/detekt-config.yml new file mode 100644 index 0000000..26ddbed --- /dev/null +++ b/Droidcon-Boston/team-props/detekt-config.yml @@ -0,0 +1,345 @@ +autoCorrect: true + +test-pattern: + active: true + patterns: + - '.*/test/.*' + - '.*Test.kt' + - '.*Spec.kt' + exclude-rule-sets: + - 'comments' + exclude-rules: + - 'NamingRules' + - 'WildcardImport' + - 'MagicNumber' + - 'MaxLineLength' + - 'LateinitUsage' + - 'StringLiteralDuplication' + - 'SpreadOperator' + - 'TooManyFunctions' + +processors: + active: true + +console-reports: + active: true + +output-reports: + active: true + +comments: + active: true + CommentOverPrivateFunction: + active: false + CommentOverPrivateProperty: + active: false + EndOfSentenceFormat: + active: false + endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!]$) + UndocumentedPublicClass: + active: false + searchInNestedClass: true + searchInInnerClass: true + searchInInnerObject: true + searchInInnerInterface: true + UndocumentedPublicFunction: + active: false + +complexity: + active: true + ComplexCondition: + active: true + ComplexInterface: + active: false + includeStaticDeclarations: false + ComplexMethod: + active: true + ignoreSingleWhenExpression: false + LabeledExpression: + active: false + LargeClass: + active: true + LongMethod: + active: true + LongParameterList: + active: true + ignoreDefaultParameters: false + MethodOverloading: + active: false + NestedBlockDepth: + active: true + StringLiteralDuplication: + active: false + ignoreAnnotation: true + excludeStringsWithLessThan5Characters: true + ignoreStringsRegex: '$^' + TooManyFunctions: + active: true + thresholdInFiles: 11 + thresholdInClasses: 11 + thresholdInInterfaces: 11 + thresholdInObjects: 11 + thresholdInEnums: 11 + +empty-blocks: + active: true + EmptyCatchBlock: + active: true + allowedExceptionNameRegex: "^(ignore|expected).*" + EmptyClassBlock: + active: true + EmptyDefaultConstructor: + active: true + EmptyDoWhileBlock: + active: true + EmptyElseBlock: + active: true + EmptyFinallyBlock: + active: true + EmptyForBlock: + active: true + EmptyFunctionBlock: + active: true + EmptyIfBlock: + active: true + EmptyInitBlock: + active: true + EmptyKtFile: + active: true + EmptySecondaryConstructor: + active: true + EmptyWhenBlock: + active: true + EmptyWhileBlock: + active: true + +exceptions: + active: true + ExceptionRaisedInUnexpectedLocation: + active: false + methodNames: 'toString,hashCode,equals,finalize' + InstanceOfCheckForException: + active: false + NotImplementedDeclaration: + active: false + PrintStackTrace: + active: false + RethrowCaughtException: + active: false + ReturnFromFinally: + active: false + SwallowedException: + active: false + ThrowingExceptionFromFinally: + active: false + ThrowingExceptionInMain: + active: false + ThrowingExceptionsWithoutMessageOrCause: + active: false + exceptions: 'IllegalArgumentException,IllegalStateException,IOException' + ThrowingNewInstanceOfSameException: + active: false + TooGenericExceptionCaught: + active: true + exceptionNames: + - ArrayIndexOutOfBoundsException + - Error + - Exception + - IllegalMonitorStateException + - NullPointerException + - IndexOutOfBoundsException + - RuntimeException + - Throwable + TooGenericExceptionThrown: + active: true + exceptionNames: + - Error + - Exception + - Throwable + - RuntimeException + +naming: + active: true + ClassNaming: + active: true + classPattern: '[A-Z$][a-zA-Z0-9$]*' + EnumNaming: + active: true + enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*' + ForbiddenClassName: + active: false + forbiddenName: '' + FunctionMaxLength: + active: false + maximumFunctionNameLength: 30 + FunctionMinLength: + active: false + minimumFunctionNameLength: 3 + FunctionNaming: + active: true + functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$' + excludeClassPattern: '$^' + MatchingDeclarationName: + active: true + MemberNameEqualsClassName: + active: false + ignoreOverriddenFunction: true + ObjectPropertyNaming: + active: true + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + PackageNaming: + active: true + packagePattern: '^[a-z]+(\.[a-z][a-z0-9]*)*$' + TopLevelPropertyNaming: + active: true + constantPattern: '[A-Z][_A-Z0-9]*' + propertyPattern: '[a-z][A-Za-z\d]*' + privatePropertyPattern: '(_)?[a-z][A-Za-z0-9]*' + VariableMaxLength: + active: false + maximumVariableNameLength: 64 + VariableMinLength: + active: false + minimumVariableNameLength: 1 + VariableNaming: + active: true + variablePattern: '[a-z][A-Za-z0-9]*' + privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + +performance: + active: true + ForEachOnRange: + active: true + SpreadOperator: + active: true + UnnecessaryTemporaryInstantiation: + active: true + +potential-bugs: + active: true + DuplicateCaseInWhenExpression: + active: true + EqualsAlwaysReturnsTrueOrFalse: + active: false + EqualsWithHashCodeExist: + active: true + ExplicitGarbageCollectionCall: + active: true + InvalidRange: + active: false + IteratorHasNextCallsNextMethod: + active: false + IteratorNotThrowingNoSuchElementException: + active: false + LateinitUsage: + active: false + excludeAnnotatedProperties: "" + ignoreOnClassesPattern: "" + UnconditionalJumpStatementInLoop: + active: false + UnreachableCode: + active: true + UnsafeCallOnNullableType: + active: false + UnsafeCast: + active: false + UselessPostfixExpression: + active: false + WrongEqualsTypeParameter: + active: false + +style: + active: true + CollapsibleIfStatements: + active: false + DataClassContainsFunctions: + active: false + conversionFunctionPrefix: 'to' + EqualsNullCall: + active: false + ExpressionBodySyntax: + active: false + ForbiddenComment: + active: true + values: 'TODO:,FIXME:,STOPSHIP:' + ForbiddenImport: + active: false + imports: '' + FunctionOnlyReturningConstant: + active: false + ignoreOverridableFunction: true + excludedFunctions: 'describeContents' + LoopWithTooManyJumpStatements: + active: false + maxJumpCount: 1 + MagicNumber: + active: true + ignoreNumbers: '-1,0,1,2' + ignoreHashCodeFunction: false + ignorePropertyDeclaration: false + ignoreConstantDeclaration: true + ignoreCompanionObjectPropertyDeclaration: true + ignoreAnnotation: false + ignoreNamedArgument: true + ignoreEnums: false + MaxLineLength: + active: true + maxLineLength: 120 + excludePackageStatements: false + excludeImportStatements: false + MayBeConst: + active: false + ModifierOrder: + active: true + NestedClassesVisibility: + active: false + NewLineAtEndOfFile: + active: true + NoTabs: + active: false + OptionalAbstractKeyword: + active: true + OptionalUnit: + active: false + OptionalWhenBraces: + active: false + ProtectedMemberInFinalClass: + active: false + RedundantVisibilityModifierRule: + active: false + ReturnCount: + active: true + max: 2 + excludedFunctions: "equals" + SafeCast: + active: true + SerialVersionUIDInSerializableClass: + active: false + SpacingBetweenPackageAndImports: + active: false + ThrowsCount: + active: true + max: 2 + TrailingWhitespace: + active: false + UnnecessaryAbstractClass: + active: false + UnnecessaryInheritance: + active: false + UnnecessaryParentheses: + active: false + UntilInsteadOfRangeTo: + active: false + UnusedImports: + active: false + UnusedPrivateMember: + active: false + UseDataClass: + active: false + excludeAnnotatedClasses: "" + UtilityClassWithPublicConstructor: + active: false + WildcardImport: + active: true + excludeImports: 'java.util.*,kotlinx.android.synthetic.*' \ No newline at end of file diff --git a/Droidcon-Boston/team-props/lint-config.xml b/Droidcon-Boston/team-props/lint-config.xml new file mode 100644 index 0000000..791d4c8 --- /dev/null +++ b/Droidcon-Boston/team-props/lint-config.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 65fce0f4f2646898b78d35e6ab5cd3ba75bb1828 Mon Sep 17 00:00:00 2001 From: n8ebel Date: Sat, 19 Jan 2019 11:28:36 -0800 Subject: [PATCH 020/173] build: add ktlint and detekt checks to build --- .circleci/config.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1a5b060..91906b0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -26,9 +26,13 @@ jobs: - .gradle key: jars-{{ checksum "Droidcon-Boston/build.gradle" }}-{{ checksum "Droidcon-Boston/app/build.gradle" }} + - run: + name: Static Analysis Checks + command: cd Droidcon-Boston && ./gradlew detekt ktlintCheck lint + - run: name: Run Tests - command: cd Droidcon-Boston && ./gradlew lint test + command: cd Droidcon-Boston && ./gradlew test - store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/ path: Droidcon-Boston/app/build/reports From d245e686b5506cece7c853780640e975b81fcf59 Mon Sep 17 00:00:00 2001 From: n8ebel Date: Mon, 21 Jan 2019 18:06:01 -0800 Subject: [PATCH 021/173] build: set initial acceptable error counts for project The project doesn't currently pass all the analysis checks, so the maxError and maxWarning values were set to match what is currently being reported as errors and warnings --- .circleci/config.yml | 2 +- Droidcon-Boston/app/build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 91906b0..ecf2c5c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -28,7 +28,7 @@ jobs: - run: name: Static Analysis Checks - command: cd Droidcon-Boston && ./gradlew detekt ktlintCheck lint + command: cd Droidcon-Boston && ./gradlew detekt ktlintCheck lint evaluateViolations - run: name: Run Tests diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index cbc48ba..3d3868f 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -59,8 +59,8 @@ android { staticAnalysis { penalty { - maxErrors = 0 - maxWarnings = 0 + maxErrors = 150 // current threshold value + maxWarnings = 70 // current threshold value } lintOptions { From adac3de5c40944fad77fc2fd280059c575d7aa72 Mon Sep 17 00:00:00 2001 From: ericmaxwell2003 Date: Sun, 27 Jan 2019 06:05:08 -0500 Subject: [PATCH 022/173] Add button to work with jump to current functionality. --- .../main/res/layout/agenda_day_fragment.xml | 21 ++++++++++++++++--- .../app/src/main/res/values/dimens.xml | 6 ++++++ .../app/src/main/res/values/strings.xml | 1 + .../app/src/main/res/values/styles.xml | 9 ++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml index cf195b0..9ecc0b1 100644 --- a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml @@ -1,14 +1,29 @@ - + + + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto"> + android:scrollbars="vertical" + tools:listitem="@layout/schedule_item" /> + + diff --git a/Droidcon-Boston/app/src/main/res/values/dimens.xml b/Droidcon-Boston/app/src/main/res/values/dimens.xml index a20d895..81ed3d6 100644 --- a/Droidcon-Boston/app/src/main/res/values/dimens.xml +++ b/Droidcon-Boston/app/src/main/res/values/dimens.xml @@ -17,4 +17,10 @@ 80dp 65dp + + + 20dp + 16dp + 20dp + \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/values/strings.xml b/Droidcon-Boston/app/src/main/res/values/strings.xml index 73feba4..6393d6d 100644 --- a/Droidcon-Boston/app/src/main/res/values/strings.xml +++ b/Droidcon-Boston/app/src/main/res/values/strings.xml @@ -50,4 +50,5 @@ Social Icon LinkedIn Icon Twitter Icon + Jump to Current diff --git a/Droidcon-Boston/app/src/main/res/values/styles.xml b/Droidcon-Boston/app/src/main/res/values/styles.xml index 6ebbf17..1f5da85 100644 --- a/Droidcon-Boston/app/src/main/res/values/styles.xml +++ b/Droidcon-Boston/app/src/main/res/values/styles.xml @@ -35,6 +35,15 @@ 20sp + + - \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/values/styles.xml b/Droidcon-Boston/app/src/main/res/values/styles.xml index 6ebbf17..19d8400 100644 --- a/Droidcon-Boston/app/src/main/res/values/styles.xml +++ b/Droidcon-Boston/app/src/main/res/values/styles.xml @@ -12,6 +12,9 @@ + \ No newline at end of file diff --git a/Droidcon-Boston/build.gradle b/Droidcon-Boston/build.gradle index 95c5a67..00345fc 100644 --- a/Droidcon-Boston/build.gradle +++ b/Droidcon-Boston/build.gradle @@ -14,7 +14,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0' + classpath 'com.android.tools.build:gradle:3.3.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From d3afb033fd6ef9d7c1022ae9385dc06b37c8c25c Mon Sep 17 00:00:00 2001 From: AdamMc331 Date: Mon, 11 Feb 2019 17:16:35 -0500 Subject: [PATCH 075/173] Moved the search dialog into AgendaDayFragment so I can actually filter once I get the results. --- .../views/agenda/AgendaDayFragment.kt | 24 ++++++++++---- .../views/agenda/AgendaFragment.kt | 20 ++--------- .../views/search/SearchDialog.kt | 33 ++++++++++++++++++- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index 4961ba2..1ca336c 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -29,8 +29,8 @@ import com.mentalmachines.droidcon_boston.data.Schedule.ScheduleRow import com.mentalmachines.droidcon_boston.data.UserAgendaRepo import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper import com.mentalmachines.droidcon_boston.utils.isNullorEmpty -import com.mentalmachines.droidcon_boston.views.MainActivity import com.mentalmachines.droidcon_boston.views.detail.AgendaDetailFragment +import com.mentalmachines.droidcon_boston.views.search.SearchDialog import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.common.FlexibleItemDecoration import eu.davidea.flexibleadapter.helpers.EmptyViewHelper @@ -87,10 +87,13 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { value } + private val searchDialog = SearchDialog() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) dayFilter = arguments?.getString(ARG_DAY) ?: "" userAgendaRepo = UserAgendaRepo.getInstance(requireContext()) + setHasOptionsMenu(true) } override fun onOptionsItemSelected(item: MenuItem?): Boolean { @@ -101,6 +104,10 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { fragmentManager.popBackStack() } } + R.id.search -> { + searchDialog.show(fragmentManager, SEARCH_DIALOG_TAG) + return true + } } return super.onOptionsItemSelected(item) } @@ -367,18 +374,21 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { } private fun listenForSearchQueries() { - (activity as? MainActivity)?.searchQuery?.observe( - viewLifecycleOwner, - androidx.lifecycle.Observer { - headerAdapter?.setFilter(it) - headerAdapter?.filterItems() - }) + searchDialog.queryListener = { query -> + headerAdapter?.setFilter(query) + headerAdapter?.filterItems() + } + } + + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + inflater?.inflate(R.menu.menu_search, menu) } companion object { private const val ARG_DAY = "day" private const val ARG_MY_AGENDA = "my_agenda" private const val MILLISECONDS_PER_INCH = 50f + private const val SEARCH_DIALOG_TAG = "agenda_search_tag" fun newInstance(myAgenda: Boolean, day: String): AgendaDayFragment { val fragment = AgendaDayFragment() diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt index 54613d1..fc000ba 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt @@ -1,10 +1,11 @@ package com.mentalmachines.droidcon_boston.views.agenda import android.os.Bundle -import android.view.* +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup import androidx.fragment.app.Fragment import com.mentalmachines.droidcon_boston.R -import com.mentalmachines.droidcon_boston.views.search.SearchDialog import kotlinx.android.synthetic.main.agenda_fragment.* import java.util.* @@ -22,7 +23,6 @@ class AgendaFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupDayPager(savedInstanceState) - setHasOptionsMenu(true) } private fun setupDayPager(savedInstanceState: Bundle?) { @@ -50,20 +50,6 @@ class AgendaFragment : Fragment() { outState.putInt(TAB_POSITION, tablayout.selectedTabPosition) } - override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { - inflater?.inflate(R.menu.menu_search, menu) - } - - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - return when (item?.itemId) { - R.id.search -> { - SearchDialog().show(fragmentManager, "SEARCH") - true - } - else -> super.onOptionsItemSelected(item) - } - } - companion object { const val TAB_POSITION = "POSITION" diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt index a32d37b..a8cc2c3 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt @@ -1,5 +1,6 @@ package com.mentalmachines.droidcon_boston.views.search +import android.content.DialogInterface import android.os.Bundle import android.text.Editable import android.text.TextWatcher @@ -11,16 +12,22 @@ import android.view.ViewGroup import android.widget.AutoCompleteTextView import android.widget.ImageView import com.mentalmachines.droidcon_boston.utils.visibleIf +import timber.log.Timber class SearchDialog : DialogFragment() { private var backButton: ImageView? = null private var clearButton: ImageView? = null private var searchInput: AutoCompleteTextView? = null + var queryListener: ((String) -> Unit)? = null + + private val currentQuery: String + get() = searchInput?.text?.toString().orEmpty() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setStyle(DialogFragment.STYLE_NORMAL, R.style.FullScreenDialogStyle); + setStyle(DialogFragment.STYLE_NORMAL, R.style.FullScreenDialogStyle) } override fun onCreateView( @@ -71,5 +78,29 @@ class SearchDialog : DialogFragment() { clearButton?.visibleIf(s?.isNotEmpty()) } }) + + searchInput?.setOnEditorActionListener { _, _, _ -> + handleQuery() + true + } + } + + private fun handleQuery() { + Timber.d("Searched for: $currentQuery") + queryListener?.invoke(currentQuery) + dismiss() + } + + /** + * In general, we can just dismiss the dialog without performing a search. However, if we + * dismiss the dialog and there is no search, we should send that out so we can clear any + * current searches. + */ + override fun onDismiss(dialog: DialogInterface?) { + if (currentQuery.isEmpty()) { + handleQuery() + } else { + super.dismiss() + } } } \ No newline at end of file From 6a5576b466c5c7188adc237a51707f4d0e6bafcf Mon Sep 17 00:00:00 2001 From: AdamMc331 Date: Mon, 11 Feb 2019 17:18:23 -0500 Subject: [PATCH 076/173] Reverted files I didn't actually need to change. --- .../app/src/main/AndroidManifest.xml | 13 +------------ .../droidcon_boston/views/MainActivity.kt | 18 ++---------------- 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/Droidcon-Boston/app/src/main/AndroidManifest.xml b/Droidcon-Boston/app/src/main/AndroidManifest.xml index deec67f..ad71820 100644 --- a/Droidcon-Boston/app/src/main/AndroidManifest.xml +++ b/Droidcon-Boston/app/src/main/AndroidManifest.xml @@ -31,18 +31,7 @@ android:name=".views.MainActivity" android:launchMode="singleTask" android:screenOrientation="portrait" - android:taskAffinity=""> - - - - - - - - - + android:taskAffinity="" /> () - val searchQuery: LiveData = _currentQuery - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main_activity) @@ -48,14 +42,6 @@ class MainActivity : AppCompatActivity() { } private fun initFragmentsFromIntent(initialIntent: Intent) { - if (Intent.ACTION_SEARCH == initialIntent.action) { - val query = initialIntent.getStringExtra(SearchManager.QUERY) - //use the query to search your data somehow - _currentQuery.value = query - return - } - - replaceFragment(getString(string.str_agenda)) val sessionDetails = initialIntent.extras?.getString(EXTRA_SESSION_DETAILS) @@ -255,7 +241,7 @@ class MainActivity : AppCompatActivity() { when (title) { resources.getString(R.string.str_agenda) -> fragment = AgendaFragment.newInstance() resources.getString(R.string.str_my_schedule) -> fragment = - AgendaFragment.newInstanceMySchedule() + AgendaFragment.newInstanceMySchedule() resources.getString(R.string.str_faq) -> fragment = FAQFragment() resources.getString(R.string.str_social) -> fragment = SocialFragment() resources.getString(R.string.str_coc) -> fragment = CocFragment() @@ -346,4 +332,4 @@ class MainActivity : AppCompatActivity() { } } } -} +} \ No newline at end of file From 25ef780c6f25dbe409a48027ae53eb165f64b5c0 Mon Sep 17 00:00:00 2001 From: AdamMc331 Date: Mon, 11 Feb 2019 17:27:13 -0500 Subject: [PATCH 077/173] Removed unused file and added some docs. --- .../views/search/SearchDialog.kt | 18 ++++++++++++++---- .../app/src/main/res/xml/searchable.xml | 4 ---- 2 files changed, 14 insertions(+), 8 deletions(-) delete mode 100644 Droidcon-Boston/app/src/main/res/xml/searchable.xml diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt index a8cc2c3..417c2f1 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt @@ -6,14 +6,19 @@ import android.text.Editable import android.text.TextWatcher import android.view.LayoutInflater import android.view.View -import androidx.fragment.app.DialogFragment -import com.mentalmachines.droidcon_boston.R import android.view.ViewGroup import android.widget.AutoCompleteTextView import android.widget.ImageView +import androidx.fragment.app.DialogFragment +import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.utils.visibleIf -import timber.log.Timber +/** + * A full screen dialog that is used to provide searching functionality in the app. + * + * @property[queryListener] A callback that should be used to be notified of any queries made by + * this dialog. + */ class SearchDialog : DialogFragment() { private var backButton: ImageView? = null private var clearButton: ImageView? = null @@ -56,6 +61,9 @@ class SearchDialog : DialogFragment() { dialog?.window?.setLayout(width, height) } + /** + * Sets all the button click and text listeners relevant to the views within our search dialog. + */ private fun setupViewListeners() { backButton?.setOnClickListener { dismiss() @@ -85,8 +93,10 @@ class SearchDialog : DialogFragment() { } } + /** + * Notifies our [queryListener] that a query has been made and dismisses the dialog. + */ private fun handleQuery() { - Timber.d("Searched for: $currentQuery") queryListener?.invoke(currentQuery) dismiss() } diff --git a/Droidcon-Boston/app/src/main/res/xml/searchable.xml b/Droidcon-Boston/app/src/main/res/xml/searchable.xml deleted file mode 100644 index 3ade3c1..0000000 --- a/Droidcon-Boston/app/src/main/res/xml/searchable.xml +++ /dev/null @@ -1,4 +0,0 @@ - - \ No newline at end of file From 51f52c8dd4ba32ff19955d5f769ea085d7046dfd Mon Sep 17 00:00:00 2001 From: AdamMc331 Date: Mon, 11 Feb 2019 17:33:05 -0500 Subject: [PATCH 078/173] Fixed random lint warnings for detekt. --- .../droidcon_boston/utils/ExtensionFunctions.kt | 5 +---- .../droidcon_boston/utils/NotificationUtils.kt | 6 +++++- .../droidcon_boston/views/agenda/AgendaDayFragment.kt | 7 ++----- .../droidcon_boston/views/search/SearchDialog.kt | 2 +- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt index f3354b4..c969b72 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/ExtensionFunctions.kt @@ -9,12 +9,10 @@ import androidx.browser.customtabs.CustomTabsIntent import androidx.core.content.ContextCompat import com.mentalmachines.droidcon_boston.R - fun String?.isNullorEmpty(): Boolean { return !(this != null && !this.isEmpty()) } - fun String.getHtmlFormattedSpanned(): Spanned { return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { Html.fromHtml(this, Html.FROM_HTML_MODE_COMPACT) @@ -23,7 +21,6 @@ fun String.getHtmlFormattedSpanned(): Spanned { } } - fun Context.loadUriInCustomTab(uriString: String) { val data = Uri.parse(uriString) val customTabsIntent = CustomTabsIntent.Builder() @@ -33,4 +30,4 @@ fun Context.loadUriInCustomTab(uriString: String) { fun View?.visibleIf(condition: Boolean?) { this?.visibility = if (condition == true) View.VISIBLE else View.GONE -} \ No newline at end of file +} diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt index 9cdcd6d..9bb097c 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/utils/NotificationUtils.kt @@ -154,7 +154,11 @@ class NotificationUtils(context: Context) : ContextWrapper(context) { pm.setComponentEnabledSetting( receiver, - if (enabled) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + if (enabled) { + PackageManager.COMPONENT_ENABLED_STATE_ENABLED + } else { + PackageManager.COMPONENT_ENABLED_STATE_DISABLED + }, PackageManager.DONT_KILL_APP ) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index 1ca336c..6d1b046 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -343,11 +343,8 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { } override fun onItemClick(view: View, position: Int): Boolean { - val adapterItem = try { - headerAdapter?.getItem(position) - } catch (e: Exception) { - null - } + val adapterItem = headerAdapter?.getItem(position) + if (adapterItem is ScheduleAdapterItem) { val itemData = adapterItem.itemData if (itemData.primarySpeakerName.isNullorEmpty()) { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt index 417c2f1..5cdce1c 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt @@ -113,4 +113,4 @@ class SearchDialog : DialogFragment() { super.dismiss() } } -} \ No newline at end of file +} From b045e3c418c3118c3a559d6c3ca9fb9602e96474 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Tue, 12 Feb 2019 00:11:19 -0500 Subject: [PATCH 079/173] Moved the listening into the activity so that both agenda fragments actually update. --- .../droidcon_boston/views/MainActivity.kt | 20 ++++++++++++++++ .../views/agenda/AgendaDayFragment.kt | 24 +++++++------------ .../views/agenda/AgendaFragment.kt | 24 +++++++++++++++---- .../app/src/main/res/layout/dialog_search.xml | 3 +++ .../app/src/main/res/values/strings.xml | 2 ++ 5 files changed, 53 insertions(+), 20 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index 19f9648..7987348 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -11,6 +11,8 @@ import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AppCompatActivity import androidx.core.view.GravityCompat import androidx.fragment.app.FragmentManager +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.R.id import com.mentalmachines.droidcon_boston.R.string @@ -19,6 +21,7 @@ import com.mentalmachines.droidcon_boston.firebase.AuthController import com.mentalmachines.droidcon_boston.utils.ServiceLocator import com.mentalmachines.droidcon_boston.views.agenda.AgendaFragment import com.mentalmachines.droidcon_boston.views.detail.AgendaDetailFragment +import com.mentalmachines.droidcon_boston.views.search.SearchDialog import com.mentalmachines.droidcon_boston.views.social.SocialFragment import com.mentalmachines.droidcon_boston.views.speaker.SpeakerFragment import com.mentalmachines.droidcon_boston.views.volunteer.VolunteerFragment @@ -30,6 +33,11 @@ class MainActivity : AppCompatActivity() { private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle private lateinit var authController: AuthController + private val _currentQuery = MutableLiveData() + val searchQuery: LiveData = _currentQuery + + private val searchDialog = SearchDialog() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main_activity) @@ -39,6 +47,12 @@ class MainActivity : AppCompatActivity() { initNavDrawerToggle() initFragmentsFromIntent(intent) + + initSearchDialog() + } + + private fun initSearchDialog() { + searchDialog.queryListener = _currentQuery::setValue } private fun initFragmentsFromIntent(initialIntent: Intent) { @@ -314,9 +328,15 @@ class MainActivity : AppCompatActivity() { } } + override fun onSearchRequested(): Boolean { + searchDialog.show(supportFragmentManager, SEARCH_DIALOG_TAG) + return true + } + companion object { private const val EXTRA_SESSIONID = "MainActivity.EXTRA_SESSIONID" private const val EXTRA_SESSION_DETAILS = "MainActivity.EXTRA_SESSION_DETAILS" + private const val SEARCH_DIALOG_TAG = "agenda_search_tag" private const val RC_SIGN_IN = 1 diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index 6d1b046..3b197e5 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -16,6 +16,7 @@ import android.view.ViewGroup import android.view.animation.DecelerateInterpolator import android.view.animation.LinearInterpolator import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearSmoothScroller import androidx.recyclerview.widget.RecyclerView @@ -29,8 +30,8 @@ import com.mentalmachines.droidcon_boston.data.Schedule.ScheduleRow import com.mentalmachines.droidcon_boston.data.UserAgendaRepo import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper import com.mentalmachines.droidcon_boston.utils.isNullorEmpty +import com.mentalmachines.droidcon_boston.views.MainActivity import com.mentalmachines.droidcon_boston.views.detail.AgendaDetailFragment -import com.mentalmachines.droidcon_boston.views.search.SearchDialog import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.common.FlexibleItemDecoration import eu.davidea.flexibleadapter.helpers.EmptyViewHelper @@ -87,13 +88,10 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { value } - private val searchDialog = SearchDialog() - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) dayFilter = arguments?.getString(ARG_DAY) ?: "" userAgendaRepo = UserAgendaRepo.getInstance(requireContext()) - setHasOptionsMenu(true) } override fun onOptionsItemSelected(item: MenuItem?): Boolean { @@ -104,10 +102,6 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { fragmentManager.popBackStack() } } - R.id.search -> { - searchDialog.show(fragmentManager, SEARCH_DIALOG_TAG) - return true - } } return super.onOptionsItemSelected(item) } @@ -371,14 +365,12 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { } private fun listenForSearchQueries() { - searchDialog.queryListener = { query -> - headerAdapter?.setFilter(query) - headerAdapter?.filterItems() - } - } - - override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { - inflater?.inflate(R.menu.menu_search, menu) + (activity as? MainActivity)?.searchQuery?.observe( + viewLifecycleOwner, + Observer { + headerAdapter?.setFilter(it) + headerAdapter?.filterItems() + }) } companion object { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt index fc000ba..a565a0d 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt @@ -1,9 +1,7 @@ package com.mentalmachines.droidcon_boston.views.agenda import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.view.* import androidx.fragment.app.Fragment import com.mentalmachines.droidcon_boston.R import kotlinx.android.synthetic.main.agenda_fragment.* @@ -11,6 +9,11 @@ import java.util.* class AgendaFragment : Fragment() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setHasOptionsMenu(true) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -19,7 +22,6 @@ class AgendaFragment : Fragment() { return inflater.inflate(R.layout.agenda_fragment, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupDayPager(savedInstanceState) @@ -50,6 +52,20 @@ class AgendaFragment : Fragment() { outState.putInt(TAB_POSITION, tablayout.selectedTabPosition) } + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + inflater?.inflate(R.menu.menu_search, menu) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + return when (item?.itemId) { + R.id.search -> { + activity?.onSearchRequested() + true + } + else -> super.onOptionsItemSelected(item) + } + } + companion object { const val TAB_POSITION = "POSITION" diff --git a/Droidcon-Boston/app/src/main/res/layout/dialog_search.xml b/Droidcon-Boston/app/src/main/res/layout/dialog_search.xml index 0b6f42d..755578d 100644 --- a/Droidcon-Boston/app/src/main/res/layout/dialog_search.xml +++ b/Droidcon-Boston/app/src/main/res/layout/dialog_search.xml @@ -22,6 +22,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:background="?android:attr/selectableItemBackground" + android:contentDescription="@string/close_search" app:srcCompat="@drawable/ic_arrow_back_black_24dp" /> diff --git a/Droidcon-Boston/app/src/main/res/values/strings.xml b/Droidcon-Boston/app/src/main/res/values/strings.xml index 5d94f61..bfc7c70 100644 --- a/Droidcon-Boston/app/src/main/res/values/strings.xml +++ b/Droidcon-Boston/app/src/main/res/values/strings.xml @@ -57,4 +57,6 @@ Jump to Current Search Speaker, Talk, Topic… + Close Search + Clear Search From de33b0cf30cbf04690ed8b2a85fcaa34d8ea6be1 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Tue, 12 Feb 2019 00:19:46 -0500 Subject: [PATCH 080/173] Handled empty filter state. --- .../views/agenda/AgendaDayFragment.kt | 4 +++- .../main/res/layout/agenda_day_fragment.xml | 20 +++++++++-------- .../src/main/res/layout/empty_filter_view.xml | 22 +++++++++++++++++++ .../app/src/main/res/values/strings.xml | 1 + 4 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 Droidcon-Boston/app/src/main/res/layout/empty_filter_view.xml diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index 3b197e5..fb2fb8e 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -53,6 +53,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private lateinit var agendaRecyler: RecyclerView private lateinit var emptyStateView: View + private lateinit var emptyFilterView: View private lateinit var scrollToCurrentButton: MaterialButton /** @@ -120,6 +121,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { // NOTE: Kotlin Extensions' agenda_vew is null in setupHeaderAdapter sporadically, so do this old school agendaRecyler = view.findViewById(R.id.agenda_recycler) emptyStateView = view.findViewById(R.id.empty_view) + emptyFilterView = view.findViewById(R.id.empty_filter_view) scrollToCurrentButton = view.findViewById(R.id.scroll_to_current_session) layoutManager = LinearLayoutManager(requireActivity().applicationContext) @@ -311,7 +313,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { .withDefaultDivider()) headerAdapter!!.expandItemsAtStartUp().setDisplayHeadersAtStartUp(true) - EmptyViewHelper(headerAdapter, emptyStateView, null, null) + EmptyViewHelper(headerAdapter, emptyStateView, emptyFilterView, null) initializeJumpButtonVariables(sortedItems) } diff --git a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml index 3651bc7..d31ffa0 100644 --- a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml @@ -1,10 +1,9 @@ - - + + android:layout_width="match_parent" + android:layout_height="match_parent"> + + + diff --git a/Droidcon-Boston/app/src/main/res/layout/empty_filter_view.xml b/Droidcon-Boston/app/src/main/res/layout/empty_filter_view.xml new file mode 100644 index 0000000..63c040c --- /dev/null +++ b/Droidcon-Boston/app/src/main/res/layout/empty_filter_view.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/values/strings.xml b/Droidcon-Boston/app/src/main/res/values/strings.xml index bfc7c70..e18d82c 100644 --- a/Droidcon-Boston/app/src/main/res/values/strings.xml +++ b/Droidcon-Boston/app/src/main/res/values/strings.xml @@ -59,4 +59,5 @@ Speaker, Talk, Topic… Close Search Clear Search + There are no talks that match this search. From 4a7452d7fb6e3ead59200eedaf8465b39ea58ea2 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Sun, 24 Feb 2019 09:38:28 -0500 Subject: [PATCH 081/173] Added a view model to the agenda day work so we can fetch the data outside of the view container. This also enabled us to switch to a replace transaction. --- .../views/agenda/AgendaDayFragment.kt | 64 ++++++++----------- .../views/agenda/AgendaDayViewModel.kt | 63 ++++++++++++++++++ .../views/detail/AgendaDetailFragment.kt | 3 +- 3 files changed, 90 insertions(+), 40 deletions(-) create mode 100644 Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index fb2fb8e..f0aff95 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -17,6 +17,9 @@ import android.view.animation.DecelerateInterpolator import android.view.animation.LinearInterpolator import androidx.fragment.app.Fragment import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearSmoothScroller import androidx.recyclerview.widget.RecyclerView @@ -43,10 +46,6 @@ import timber.log.Timber class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private val timeHeaders = HashMap() - private var dayFilter: String = "" - private val firebaseHelper = FirebaseHelper.instance - private var onlyMyAgenda: Boolean = false - private lateinit var userAgendaRepo: UserAgendaRepo private var headerAdapter: FlexibleAdapter<*>? = null private lateinit var layoutManager: LinearLayoutManager @@ -55,6 +54,18 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private lateinit var emptyStateView: View private lateinit var emptyFilterView: View private lateinit var scrollToCurrentButton: MaterialButton + private lateinit var viewModel: AgendaDayViewModel + + private val viewModelFactory = object : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + val dayFilter = arguments?.getString(ARG_DAY) ?: "" + val onlyMyAgenda = arguments?.getBoolean(ARG_MY_AGENDA) ?: false + val userAgendaRepo = UserAgendaRepo.getInstance(requireContext()) + + @Suppress("UNCHECKED_CAST") + return AgendaDayViewModel(dayFilter, onlyMyAgenda, userAgendaRepo) as T + } + } /** * Total number of sessions that begin after now and end before now. @@ -89,10 +100,13 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { value } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - dayFilter = arguments?.getString(ARG_DAY) ?: "" - userAgendaRepo = UserAgendaRepo.getInstance(requireContext()) + private fun initViewModel() { + viewModel = + ViewModelProviders.of(this, viewModelFactory).get(AgendaDayViewModel::class.java) + + viewModel.scheduleRows.observe(viewLifecycleOwner, Observer { + it?.let(this::setupHeaderAdapter) + }) } override fun onOptionsItemSelected(item: MenuItem?): Boolean { @@ -126,7 +140,6 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { layoutManager = LinearLayoutManager(requireActivity().applicationContext) agendaRecyler.layoutManager = layoutManager - onlyMyAgenda = arguments?.getBoolean(ARG_MY_AGENDA) ?: false val linearSmoothScroller = setupSmoothScroller() addFloatingAnimation() @@ -137,6 +150,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { ) } + initViewModel() fetchScheduleData() activity?.supportFragmentManager?.addOnBackStackChangedListener(backStackChangeListener) @@ -144,7 +158,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { } private val backStackChangeListener: () -> Unit = { - if (onlyMyAgenda) { + if (viewModel.onlyMyAgenda) { fetchScheduleData() } else { headerAdapter?.notifyDataSetChanged() @@ -231,7 +245,6 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { override fun onDestroyView() { super.onDestroyView() agendaRecyler.removeOnChildAttachStateChangeListener(currentSessionVisibleListener) - firebaseHelper.eventDatabase.removeEventListener(dataListener) activity?.supportFragmentManager?.removeOnBackStackChangedListener(backStackChangeListener) } @@ -239,35 +252,8 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { agendaRecyler.adapter?.notifyDataSetChanged() } - private val dataListener: ValueEventListener = object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - val rows = ArrayList() - for (roomSnapshot in dataSnapshot.children) { - val key = roomSnapshot.key ?: "" - val data = roomSnapshot.getValue(ScheduleEvent::class.java) - Timber.d("Event: $data") - if (data != null) { - val scheduleRow = data.toScheduleRow(key) - val matchesDay = scheduleRow.date == dayFilter - val isPublicView = !onlyMyAgenda - val isPrivateAndBookmarked = onlyMyAgenda && userAgendaRepo - .isSessionBookmarked(scheduleRow.id) - - if (matchesDay && (isPublicView || isPrivateAndBookmarked)) { - rows.add(scheduleRow) - } - } - } - setupHeaderAdapter(rows) - } - - override fun onCancelled(databaseError: DatabaseError) { - Timber.e(databaseError.toException()) - } - } - private fun fetchScheduleData() { - firebaseHelper.eventDatabase.addValueEventListener(dataListener) + viewModel.fetchScheduleData() } private val currentSessionVisibleListener = diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt new file mode 100644 index 0000000..45b9e34 --- /dev/null +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt @@ -0,0 +1,63 @@ +package com.mentalmachines.droidcon_boston.views.agenda + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.google.firebase.database.DataSnapshot +import com.google.firebase.database.DatabaseError +import com.google.firebase.database.ValueEventListener +import com.mentalmachines.droidcon_boston.data.FirebaseDatabase +import com.mentalmachines.droidcon_boston.data.Schedule +import com.mentalmachines.droidcon_boston.data.UserAgendaRepo +import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper +import timber.log.Timber + +class AgendaDayViewModel( + private val dayFilter: String, + val onlyMyAgenda: Boolean, + private val userAgendaRepo: UserAgendaRepo +) : ViewModel() { + private val firebaseHelper = FirebaseHelper.instance + + private val _scheduleRows = MutableLiveData>() + val scheduleRows: LiveData> = _scheduleRows + + private val dataListener: ValueEventListener = object : ValueEventListener { + override fun onDataChange(dataSnapshot: DataSnapshot) { + val rows = ArrayList() + for (roomSnapshot in dataSnapshot.children) { + val key = roomSnapshot.key ?: "" + val data = roomSnapshot.getValue(FirebaseDatabase.ScheduleEvent::class.java) + Timber.d("Event: $data") + if (data != null) { + val scheduleRow = data.toScheduleRow(key) + val matchesDay = scheduleRow.date == dayFilter + val isPublicView = !onlyMyAgenda + val isPrivateAndBookmarked = onlyMyAgenda && userAgendaRepo + .isSessionBookmarked(scheduleRow.id) + + if (matchesDay && (isPublicView || isPrivateAndBookmarked)) { + rows.add(scheduleRow) + } + } + } + + _scheduleRows.value = rows + } + + override fun onCancelled(databaseError: DatabaseError) { + Timber.e(databaseError.toException()) + } + } + + fun fetchScheduleData() { + if (scheduleRows.value == null) { + firebaseHelper.eventDatabase.addValueEventListener(dataListener) + } + } + + override fun onCleared() { + super.onCleared() + firebaseHelper.eventDatabase.removeEventListener(dataListener) + } +} \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt index 1004582..496c460 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt @@ -232,7 +232,8 @@ class AgendaDetailFragment : Fragment() { agendaDetailFragment.arguments = arguments supportFragmentManager.beginTransaction() - .add(R.id.fragment_container, agendaDetailFragment).addToBackStack(null).commit() + .replace(R.id.fragment_container, agendaDetailFragment) + .addToBackStack(null).commit() } } } From 4a2b8dad1c8d3b2f8b84a91a751400edb8fb1e85 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Sun, 24 Feb 2019 09:55:48 -0500 Subject: [PATCH 082/173] A little more refactoring but now searching and filtering is a bit smoother. --- .../views/agenda/AgendaDayFragment.kt | 4 +--- .../views/agenda/AgendaDayViewModel.kt | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index f0aff95..88c9fda 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -356,8 +356,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { (activity as? MainActivity)?.searchQuery?.observe( viewLifecycleOwner, Observer { - headerAdapter?.setFilter(it) - headerAdapter?.filterItems() + it?.let(viewModel::setActiveFilter) }) } @@ -365,7 +364,6 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private const val ARG_DAY = "day" private const val ARG_MY_AGENDA = "my_agenda" private const val MILLISECONDS_PER_INCH = 50f - private const val SEARCH_DIALOG_TAG = "agenda_search_tag" fun newInstance(myAgenda: Boolean, day: String): AgendaDayFragment { val fragment = AgendaDayFragment() diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt index 45b9e34..0988d01 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt @@ -2,6 +2,7 @@ package com.mentalmachines.droidcon_boston.views.agenda import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.Transformations import androidx.lifecycle.ViewModel import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError @@ -20,7 +21,16 @@ class AgendaDayViewModel( private val firebaseHelper = FirebaseHelper.instance private val _scheduleRows = MutableLiveData>() - val scheduleRows: LiveData> = _scheduleRows + private val _activeFilter = MutableLiveData() + + val scheduleRows: LiveData> = Transformations.map(_activeFilter) { + constraint -> + _scheduleRows.value?.filter { itemData -> + (itemData.talkTitle.contains(constraint, ignoreCase = true) + || itemData.talkDescription.contains(constraint, ignoreCase = true) + || itemData.speakerNames.any { it.contains(constraint, ignoreCase = true) }) + } + } private val dataListener: ValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { @@ -43,6 +53,7 @@ class AgendaDayViewModel( } _scheduleRows.value = rows + _activeFilter.value = "" } override fun onCancelled(databaseError: DatabaseError) { @@ -56,6 +67,10 @@ class AgendaDayViewModel( } } + fun setActiveFilter(filter: String) { + _activeFilter.value = filter + } + override fun onCleared() { super.onCleared() firebaseHelper.eventDatabase.removeEventListener(dataListener) From 0ef82af9de46eea759abc6e51c8e498501d19c0e Mon Sep 17 00:00:00 2001 From: adammc331 Date: Sun, 24 Feb 2019 09:58:52 -0500 Subject: [PATCH 083/173] Removed unused filtering code from previous change and added comment. --- .../views/agenda/AgendaDayViewModel.kt | 4 ++++ .../views/agenda/ScheduleAdapterItem.kt | 14 +------------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt index 0988d01..274fd79 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt @@ -23,6 +23,10 @@ class AgendaDayViewModel( private val _scheduleRows = MutableLiveData>() private val _activeFilter = MutableLiveData() + /** + * Whenever an active filter is set, we filter out the [_scheduleRows] for any that contain the + * filter within the title, description, or speaker names. + */ val scheduleRows: LiveData> = Transformations.map(_activeFilter) { constraint -> _scheduleRows.value?.filter { itemData -> diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt index 7351cfd..5030288 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt @@ -13,7 +13,6 @@ import com.mentalmachines.droidcon_boston.data.UserAgendaRepo import com.mentalmachines.droidcon_boston.views.transform.CircleTransform import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.AbstractSectionableItem -import eu.davidea.flexibleadapter.items.IFilterable import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.viewholders.FlexibleViewHolder import timber.log.Timber @@ -30,8 +29,7 @@ class ScheduleAdapterItem internal constructor( val itemData: Schedule.ScheduleRow, header: ScheduleAdapterItemHeader ) : - AbstractSectionableItem(header), - IFilterable { + AbstractSectionableItem(header) { private var startTime: Date = Date() @@ -207,14 +205,4 @@ class ScheduleAdapterItem internal constructor( sessionLayout = parent.findViewById(R.id.session_layout) } } - - override fun filter(constraint: String?): Boolean { - return if (constraint == null) { - true - } else { - (itemData.talkTitle.contains(constraint, ignoreCase = true) - || itemData.talkDescription.contains(constraint, ignoreCase = true) - || itemData.speakerNames.any { it.contains(constraint, ignoreCase = true) }) - } - } } From 7eec5b7d5c87405db29889892be808caf9e546c2 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Sun, 24 Feb 2019 11:09:22 -0500 Subject: [PATCH 084/173] Some lint warnings. --- .../firebase/DbFirebaseMessagingService.kt | 6 +++++- .../droidcon_boston/views/agenda/AgendaFragment.kt | 13 +++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt index fb9133b..4896f09 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/firebase/DbFirebaseMessagingService.kt @@ -33,8 +33,12 @@ class DbFirebaseMessagingService : FirebaseMessagingService() { notificationUtils.sendAndroidChannelNotification( getString(R.string.conference_name), bodyStr!!, - 101 + NOTIFICATION_ID ) } } + + companion object { + private const val NOTIFICATION_ID = 101 + } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt index a565a0d..300f3d6 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt @@ -1,7 +1,12 @@ package com.mentalmachines.droidcon_boston.views.agenda import android.os.Bundle -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.fragment.app.Fragment import com.mentalmachines.droidcon_boston.R import kotlinx.android.synthetic.main.agenda_fragment.* @@ -38,7 +43,7 @@ class AgendaFragment : Fragment() { // set current day to second if today matches val today = Calendar.getInstance() val dayTwo = Calendar.getInstance() - dayTwo.set(2018, Calendar.MARCH, 27) + dayTwo.set(EVENT_YEAR, EVENT_MONTH, EVENT_DAY_ONE) if (today == dayTwo) { viewpager.currentItem = 1 } @@ -82,5 +87,9 @@ class AgendaFragment : Fragment() { fragment.arguments = args return fragment } + + private const val EVENT_YEAR = 2018 + private const val EVENT_MONTH = Calendar.MARCH + private const val EVENT_DAY_ONE = 27 } } From 224c38203878efb8a986dda37e38d158c0cd30d0 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Sun, 24 Feb 2019 23:05:22 -0500 Subject: [PATCH 085/173] Refactored the keyword checking and added a unit test. --- .../droidcon_boston/data/Schedule.kt | 6 +++ .../views/agenda/AgendaDayViewModel.kt | 12 +++--- .../droidcon_boston/data/ScheduleTest.kt | 39 +++++++++++++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt index 91bf71f..d0ead4c 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt @@ -32,6 +32,12 @@ class Schedule { fun hasMultipleSpeakers(): Boolean = speakerNames.size > 1 fun getSpeakerString(): String? = speakerNames.joinToString(", ") + + fun containsKeyword(keyword: String): Boolean { + return this.talkTitle.contains(keyword, ignoreCase = true) + || this.talkDescription.contains(keyword, ignoreCase = true) + || this.speakerNames.any { it.contains(keyword, ignoreCase = true) } + } } data class ScheduleDetail( diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt index 274fd79..4e84012 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayViewModel.kt @@ -27,14 +27,12 @@ class AgendaDayViewModel( * Whenever an active filter is set, we filter out the [_scheduleRows] for any that contain the * filter within the title, description, or speaker names. */ - val scheduleRows: LiveData> = Transformations.map(_activeFilter) { - constraint -> - _scheduleRows.value?.filter { itemData -> - (itemData.talkTitle.contains(constraint, ignoreCase = true) - || itemData.talkDescription.contains(constraint, ignoreCase = true) - || itemData.speakerNames.any { it.contains(constraint, ignoreCase = true) }) + val scheduleRows: LiveData> = + Transformations.map(_activeFilter) { constraint -> + _scheduleRows.value?.filter { itemData -> + itemData.containsKeyword(constraint) + } } - } private val dataListener: ValueEventListener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { diff --git a/Droidcon-Boston/app/src/test/java/com/mentalmachines/droidcon_boston/data/ScheduleTest.kt b/Droidcon-Boston/app/src/test/java/com/mentalmachines/droidcon_boston/data/ScheduleTest.kt index 73d7f2b..d787ec2 100644 --- a/Droidcon-Boston/app/src/test/java/com/mentalmachines/droidcon_boston/data/ScheduleTest.kt +++ b/Droidcon-Boston/app/src/test/java/com/mentalmachines/droidcon_boston/data/ScheduleTest.kt @@ -65,4 +65,43 @@ class ScheduleTest { row.speakerNames = Arrays.asList(s1, s2) assertEquals("$s1, $s2", row.getSpeakerString()) } + + @Test + fun containsKeywordInTitle() { + val keyword = "Kotlin" + val testTitle = "All About $keyword" + + val row = ScheduleRow(talkTitle = testTitle) + assertTrue(row.containsKeyword(keyword)) + } + + @Test + fun containsKeywordInDescription() { + val keyword = "Kotlin" + val testDescription = "All about $keyword" + + val row = ScheduleRow(talkDescription = testDescription) + assertTrue(row.containsKeyword(keyword)) + } + + @Test + fun containsKeywordInSpeakerName() { + val keyword = "Kotlin" + val speakers = listOf("Speaker about $keyword") + + val row = ScheduleRow(speakerNames = speakers) + assertTrue(row.containsKeyword(keyword)) + } + + @Test + fun containsEmptyKeyword() { + val row = ScheduleRow() + assertTrue(row.containsKeyword("")) + } + + @Test + fun doesNotContainKeyword() { + val row = ScheduleRow() + assertFalse(row.containsKeyword("Blah")) + } } From dd1ebe21a04323df54797ce5466556f8000f5bde Mon Sep 17 00:00:00 2001 From: Ken Yee Date: Mon, 18 Feb 2019 15:14:50 -0500 Subject: [PATCH 086/173] switch app to use 2019 DB --- Droidcon-Boston/app/google-services.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Droidcon-Boston/app/google-services.json b/Droidcon-Boston/app/google-services.json index 4b01613..5536e7e 100644 --- a/Droidcon-Boston/app/google-services.json +++ b/Droidcon-Boston/app/google-services.json @@ -1,7 +1,7 @@ { "project_info": { "project_number": "1084321061238", - "firebase_url": "https://droidcon-bos.firebaseio.com", + "firebase_url": "https://droidcon-bos-2019.firebaseio.com", "project_id": "droidcon-bos", "storage_bucket": "droidcon-bos.appspot.com" }, From d6551ea94157c29b251271fb149c7f59170fd014 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Tue, 26 Feb 2019 22:15:37 -0500 Subject: [PATCH 087/173] Early attempts at auto complete. --- Droidcon-Boston/app/build.gradle | 4 ++ .../droidcon_boston/data/Schedule.kt | 9 ++- .../droidcon_boston/views/MainActivity.kt | 3 + .../views/search/ScheduleSearchAdapter.kt | 62 +++++++++++++++++++ .../views/search/SearchDialog.kt | 31 ++++++++++ .../views/search/SearchViewModel.kt | 47 ++++++++++++++ .../res/layout/list_item_schedule_search.xml | 18 ++++++ 7 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt create mode 100644 Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt create mode 100644 Droidcon-Boston/app/src/main/res/layout/list_item_schedule_search.xml diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index 93e4cc5..8e08f69 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -56,6 +56,10 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + androidExtensions { + experimental = true + } } staticAnalysis { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt index d0ead4c..d155de1 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt @@ -1,5 +1,7 @@ package com.mentalmachines.droidcon_boston.data +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize import java.util.* @@ -8,6 +10,7 @@ import java.util.* */ class Schedule { + @Parcelize data class ScheduleRow( var primarySpeakerName: String = "", var id: String = "", @@ -25,7 +28,7 @@ class Schedule { var photoUrlMap: HashMap = HashMap(0), var isOver: Boolean = false, var isCurrentSession: Boolean = false - ) { + ) : Parcelable { fun hasSpeaker(): Boolean = speakerNames.isNotEmpty() @@ -38,6 +41,10 @@ class Schedule { || this.talkDescription.contains(keyword, ignoreCase = true) || this.speakerNames.any { it.contains(keyword, ignoreCase = true) } } + + override fun toString(): String { + return talkTitle + } } data class ScheduleDetail( diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index 7987348..8506f70 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -53,6 +53,9 @@ class MainActivity : AppCompatActivity() { private fun initSearchDialog() { searchDialog.queryListener = _currentQuery::setValue + searchDialog.itemClicked = { + AgendaDetailFragment.addDetailFragmentToStack(supportFragmentManager, it) + } } private fun initFragmentsFromIntent(initialIntent: Intent) { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt new file mode 100644 index 0000000..238f27d --- /dev/null +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt @@ -0,0 +1,62 @@ +package com.mentalmachines.droidcon_boston.views.search + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import android.widget.Filter +import android.widget.TextView +import com.mentalmachines.droidcon_boston.R +import com.mentalmachines.droidcon_boston.data.Schedule + +class ScheduleSearchAdapter( + context: Context, + private val layoutRes: Int, + private val scheduleRows: List +): ArrayAdapter(context, layoutRes, scheduleRows) { + + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + val view = convertView ?: LayoutInflater.from(context).inflate(layoutRes, parent, false) + + val scheduleRow = getItem(position) + view.findViewById(R.id.talk_title).text = scheduleRow?.talkTitle.orEmpty() + + return view + } + + override fun getItem(position: Int): Schedule.ScheduleRow? { + return scheduleRows[position] + } + + override fun getCount(): Int { + return scheduleRows.size + } + + override fun getFilter(): Filter { + return object : Filter() { + override fun performFiltering(constraint: CharSequence?): FilterResults { + val suggestions = scheduleRows.filter { + it.containsKeyword(constraint?.toString().orEmpty()) + } + + return FilterResults().apply { + values = suggestions + count = suggestions.size + } + } + + override fun publishResults(constraint: CharSequence?, results: FilterResults?) { + clear() + + (results?.values as? List<*>) + ?.filterIsInstance(Schedule.ScheduleRow::class.java) + ?.forEach { + add(it) + } + + notifyDataSetChanged() + } + } + } +} \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt index 5cdce1c..5616506 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt @@ -10,7 +10,10 @@ import android.view.ViewGroup import android.widget.AutoCompleteTextView import android.widget.ImageView import androidx.fragment.app.DialogFragment +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProviders import com.mentalmachines.droidcon_boston.R +import com.mentalmachines.droidcon_boston.data.Schedule import com.mentalmachines.droidcon_boston.utils.visibleIf /** @@ -25,14 +28,18 @@ class SearchDialog : DialogFragment() { private var searchInput: AutoCompleteTextView? = null var queryListener: ((String) -> Unit)? = null + var itemClicked: ((Schedule.ScheduleRow) -> Unit)? = null private val currentQuery: String get() = searchInput?.text?.toString().orEmpty() + private lateinit var viewModel: SearchViewModel + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(DialogFragment.STYLE_NORMAL, R.style.FullScreenDialogStyle) + viewModel = ViewModelProviders.of(this).get(SearchViewModel::class.java) } override fun onCreateView( @@ -51,6 +58,7 @@ class SearchDialog : DialogFragment() { searchInput = view.findViewById(R.id.search_input) setupViewListeners() + listenForSchedule() } override fun onStart() { @@ -61,6 +69,20 @@ class SearchDialog : DialogFragment() { dialog?.window?.setLayout(width, height) } + private fun listenForSchedule() { + viewModel.scheduleRows.observe(viewLifecycleOwner, Observer(this::setupSearchAdapter)) + } + + private fun setupSearchAdapter(suggestions: List?) { + val adapter = ScheduleSearchAdapter( + requireContext(), + R.layout.list_item_schedule_search, + suggestions.orEmpty() + ) + + searchInput?.setAdapter(adapter) + } + /** * Sets all the button click and text listeners relevant to the views within our search dialog. */ @@ -91,6 +113,15 @@ class SearchDialog : DialogFragment() { handleQuery() true } + + searchInput?.setOnItemClickListener { _, _, position, _ -> + val adapter = (searchInput?.adapter as? ScheduleSearchAdapter) + val item = adapter?.getItem(position) + item?.let { + itemClicked?.invoke(it) + dismiss() + } + } } /** diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt new file mode 100644 index 0000000..02d5fd0 --- /dev/null +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt @@ -0,0 +1,47 @@ +package com.mentalmachines.droidcon_boston.views.search + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.google.firebase.database.DataSnapshot +import com.google.firebase.database.DatabaseError +import com.google.firebase.database.ValueEventListener +import com.mentalmachines.droidcon_boston.data.FirebaseDatabase +import com.mentalmachines.droidcon_boston.data.Schedule +import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper +import timber.log.Timber + +class SearchViewModel : ViewModel() { + private val firebaseHelper = FirebaseHelper.instance + + private val _scheduleRows = MutableLiveData>() + val scheduleRows: LiveData> = _scheduleRows + + private val dataListener: ValueEventListener = object : ValueEventListener { + override fun onDataChange(dataSnapshot: DataSnapshot) { + val rows = ArrayList() + for (roomSnapshot in dataSnapshot.children) { + val key = roomSnapshot.key ?: "" + val data = roomSnapshot.getValue(FirebaseDatabase.ScheduleEvent::class.java) + if (data != null) { + rows.add(data.toScheduleRow(key)) + } + } + + _scheduleRows.value = rows + } + + override fun onCancelled(databaseError: DatabaseError) { + Timber.e(databaseError.toException()) + } + } + + init { + firebaseHelper.eventDatabase.addValueEventListener(dataListener) + } + + override fun onCleared() { + super.onCleared() + firebaseHelper.eventDatabase.removeEventListener(dataListener) + } +} \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/list_item_schedule_search.xml b/Droidcon-Boston/app/src/main/res/layout/list_item_schedule_search.xml new file mode 100644 index 0000000..bf1a7a0 --- /dev/null +++ b/Droidcon-Boston/app/src/main/res/layout/list_item_schedule_search.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file From e4977710d0f30dc7d12f748633e6186d5f9f072d Mon Sep 17 00:00:00 2001 From: adammc331 Date: Sat, 2 Mar 2019 15:36:20 -0500 Subject: [PATCH 088/173] Fixed the way we apply the title to selections, and also made sure backing up in search still filters for #153. --- .../droidcon_boston/data/Schedule.kt | 4 --- .../views/search/ScheduleSearchAdapter.kt | 25 +++++++++++++------ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt index d155de1..a51745f 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt @@ -41,10 +41,6 @@ class Schedule { || this.talkDescription.contains(keyword, ignoreCase = true) || this.speakerNames.any { it.contains(keyword, ignoreCase = true) } } - - override fun toString(): String { - return talkTitle - } } data class ScheduleDetail( diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt index 238f27d..5c32a11 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt @@ -15,6 +15,8 @@ class ScheduleSearchAdapter( private val layoutRes: Int, private val scheduleRows: List ): ArrayAdapter(context, layoutRes, scheduleRows) { + private val suggestions: MutableList = mutableListOf() + private val tempItems: MutableList = scheduleRows.toMutableList() override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { val view = convertView ?: LayoutInflater.from(context).inflate(layoutRes, parent, false) @@ -36,8 +38,14 @@ class ScheduleSearchAdapter( override fun getFilter(): Filter { return object : Filter() { override fun performFiltering(constraint: CharSequence?): FilterResults { - val suggestions = scheduleRows.filter { - it.containsKeyword(constraint?.toString().orEmpty()) + val keyword = constraint ?: return FilterResults() + + suggestions.clear() + + tempItems.forEach { + if (it.containsKeyword(keyword.toString())) { + suggestions.add(it) + } } return FilterResults().apply { @@ -47,16 +55,19 @@ class ScheduleSearchAdapter( } override fun publishResults(constraint: CharSequence?, results: FilterResults?) { + val tempValues = (results?.values as? List<*>) + ?.filterIsInstance(Schedule.ScheduleRow::class.java) + clear() - (results?.values as? List<*>) - ?.filterIsInstance(Schedule.ScheduleRow::class.java) - ?.forEach { - add(it) - } + tempValues?.forEach(this@ScheduleSearchAdapter::add) notifyDataSetChanged() } + + override fun convertResultToString(resultValue: Any?): CharSequence { + return (resultValue as? Schedule.ScheduleRow)?.talkTitle.toString() + } } } } \ No newline at end of file From 0021c0bafea5289bcab58645e7a99541349e4496 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Sat, 2 Mar 2019 15:52:53 -0500 Subject: [PATCH 089/173] Added talk description to the dropdown items for #153. --- .../views/search/ScheduleSearchAdapter.kt | 6 +++++- .../app/src/main/res/layout/dialog_search.xml | 2 +- .../main/res/layout/list_item_schedule_search.xml | 13 +++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt index 5c32a11..8f404cb 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt @@ -1,6 +1,7 @@ package com.mentalmachines.droidcon_boston.views.search import android.content.Context +import android.text.Html import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -14,7 +15,7 @@ class ScheduleSearchAdapter( context: Context, private val layoutRes: Int, private val scheduleRows: List -): ArrayAdapter(context, layoutRes, scheduleRows) { +) : ArrayAdapter(context, layoutRes, scheduleRows) { private val suggestions: MutableList = mutableListOf() private val tempItems: MutableList = scheduleRows.toMutableList() @@ -23,6 +24,9 @@ class ScheduleSearchAdapter( val scheduleRow = getItem(position) view.findViewById(R.id.talk_title).text = scheduleRow?.talkTitle.orEmpty() + @Suppress("DEPRECATION") + view.findViewById(R.id.talk_description).text = + Html.fromHtml(scheduleRow?.talkDescription) return view } diff --git a/Droidcon-Boston/app/src/main/res/layout/dialog_search.xml b/Droidcon-Boston/app/src/main/res/layout/dialog_search.xml index 755578d..51cba7e 100644 --- a/Droidcon-Boston/app/src/main/res/layout/dialog_search.xml +++ b/Droidcon-Boston/app/src/main/res/layout/dialog_search.xml @@ -35,7 +35,7 @@ android:focusableInTouchMode="true" android:hint="@string/search_hint" android:imeOptions="actionSearch|flagNoExtractUi" - android:inputType="text" + android:inputType="textCapWords" android:maxLines="1" android:paddingLeft="16dp" android:paddingRight="16dp" diff --git a/Droidcon-Boston/app/src/main/res/layout/list_item_schedule_search.xml b/Droidcon-Boston/app/src/main/res/layout/list_item_schedule_search.xml index bf1a7a0..f1458ce 100644 --- a/Droidcon-Boston/app/src/main/res/layout/list_item_schedule_search.xml +++ b/Droidcon-Boston/app/src/main/res/layout/list_item_schedule_search.xml @@ -11,8 +11,21 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:textColor="@android:color/black" + android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + \ No newline at end of file From cc9329604c54f7135ac0d50b55ccd75023020e75 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Sat, 2 Mar 2019 16:10:36 -0500 Subject: [PATCH 090/173] Fixed a few variable names to make detekt happy. --- .../views/agenda/AgendaDayPagerAdapter.kt | 4 +-- .../views/faq/FaqAdapterItem.kt | 26 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt index ec35e83..c6ffc56 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt @@ -10,11 +10,11 @@ class AgendaDayPagerAdapter internal constructor( ) : FixedFragmentStatePagerAdapter(fm) { - private val PAGE_COUNT = 2 + private val pageCount = 2 private val tabTitles = arrayOf("Day 1", "Day 2") override fun getCount(): Int { - return PAGE_COUNT + return pageCount } override fun getItem(position: Int): Fragment { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt index 46b1db8..7ee51d5 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/faq/FaqAdapterItem.kt @@ -49,14 +49,14 @@ class FaqAdapterItem internal constructor(val itemData: Answer, header: FaqAdapt payloads: MutableList ) { - holder.faq_text.text = itemData.answer + holder.faqText.text = itemData.answer if (!TextUtils.isEmpty(itemData.photoLink)) { - val context = holder.faq_text.context + val context = holder.faqText.context Glide.with(context).load(itemData.photoLink).crossFade().centerCrop() - .into(holder.faq_photo) - holder.faq_photo.visibility = View.VISIBLE + .into(holder.faqPhoto) + holder.faqPhoto.visibility = View.VISIBLE } else { - holder.faq_photo.visibility = View.GONE + holder.faqPhoto.visibility = View.GONE } if (!TextUtils.isEmpty(itemData.otherLink) || !TextUtils.isEmpty(itemData.mapLink)) { @@ -66,24 +66,24 @@ class FaqAdapterItem internal constructor(val itemData: Answer, header: FaqAdapt private fun addBackgroundRipple(holder: ViewHolder) { val outValue = TypedValue() - val context = holder.faq_text.context + val context = holder.faqText.context context.theme.resolveAttribute(android.R.attr.selectableItemBackground, outValue, true) - holder.root_layout.setBackgroundResource(outValue.resourceId) + holder.rootLayout.setBackgroundResource(outValue.resourceId) } class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter) { - lateinit var root_layout: View + lateinit var rootLayout: View - lateinit var faq_text: TextView + lateinit var faqText: TextView - lateinit var faq_photo: ImageView + lateinit var faqPhoto: ImageView private fun findViews(parent: View) { - root_layout = parent.findViewById(R.id.root_layout) - faq_text = parent.findViewById(R.id.faq_text) - faq_photo = parent.findViewById(R.id.faq_photo) + rootLayout = parent.findViewById(R.id.root_layout) + faqText = parent.findViewById(R.id.faq_text) + faqPhoto = parent.findViewById(R.id.faq_photo) } init { From ec3d949108e42952730999ee81708115bce6cd5f Mon Sep 17 00:00:00 2001 From: adammc331 Date: Mon, 4 Mar 2019 20:32:29 -0500 Subject: [PATCH 091/173] Removed unnecessary search functionality now that we have the drop down. --- .../droidcon_boston/views/MainActivity.kt | 6 ---- .../views/agenda/AgendaDayFragment.kt | 16 --------- .../views/search/ScheduleSearchAdapter.kt | 8 ++++- .../views/search/SearchDialog.kt | 34 ------------------- .../views/search/SearchViewModel.kt | 7 +++- 5 files changed, 13 insertions(+), 58 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt index 8506f70..9dcb817 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/MainActivity.kt @@ -11,8 +11,6 @@ import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AppCompatActivity import androidx.core.view.GravityCompat import androidx.fragment.app.FragmentManager -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.R.id import com.mentalmachines.droidcon_boston.R.string @@ -33,9 +31,6 @@ class MainActivity : AppCompatActivity() { private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle private lateinit var authController: AuthController - private val _currentQuery = MutableLiveData() - val searchQuery: LiveData = _currentQuery - private val searchDialog = SearchDialog() override fun onCreate(savedInstanceState: Bundle?) { @@ -52,7 +47,6 @@ class MainActivity : AppCompatActivity() { } private fun initSearchDialog() { - searchDialog.queryListener = _currentQuery::setValue searchDialog.itemClicked = { AgendaDetailFragment.addDetailFragmentToStack(supportFragmentManager, it) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index 88c9fda..df88ca9 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -24,16 +24,10 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearSmoothScroller import androidx.recyclerview.widget.RecyclerView import com.google.android.material.button.MaterialButton -import com.google.firebase.database.DataSnapshot -import com.google.firebase.database.DatabaseError -import com.google.firebase.database.ValueEventListener import com.mentalmachines.droidcon_boston.R -import com.mentalmachines.droidcon_boston.data.FirebaseDatabase.ScheduleEvent import com.mentalmachines.droidcon_boston.data.Schedule.ScheduleRow import com.mentalmachines.droidcon_boston.data.UserAgendaRepo -import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper import com.mentalmachines.droidcon_boston.utils.isNullorEmpty -import com.mentalmachines.droidcon_boston.views.MainActivity import com.mentalmachines.droidcon_boston.views.detail.AgendaDetailFragment import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.common.FlexibleItemDecoration @@ -46,7 +40,6 @@ import timber.log.Timber class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private val timeHeaders = HashMap() - private lateinit var userAgendaRepo: UserAgendaRepo private var headerAdapter: FlexibleAdapter<*>? = null private lateinit var layoutManager: LinearLayoutManager @@ -154,7 +147,6 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { fetchScheduleData() activity?.supportFragmentManager?.addOnBackStackChangedListener(backStackChangeListener) - listenForSearchQueries() } private val backStackChangeListener: () -> Unit = { @@ -352,14 +344,6 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { return true } - private fun listenForSearchQueries() { - (activity as? MainActivity)?.searchQuery?.observe( - viewLifecycleOwner, - Observer { - it?.let(viewModel::setActiveFilter) - }) - } - companion object { private const val ARG_DAY = "day" private const val ARG_MY_AGENDA = "my_agenda" diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt index 8f404cb..f81ca45 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/ScheduleSearchAdapter.kt @@ -69,8 +69,14 @@ class ScheduleSearchAdapter( notifyDataSetChanged() } + /** + * Since our search dropdown includes actual talks, and not topics the user can suggest, + * we don't want to persist that inside the AutoCompleteTextView after all. We want + * to make it easy for them to click search and begin typing in the new thing, so we can + * just use an empty string here. + */ override fun convertResultToString(resultValue: Any?): CharSequence { - return (resultValue as? Schedule.ScheduleRow)?.talkTitle.toString() + return "" } } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt index 5616506..71183c8 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchDialog.kt @@ -1,6 +1,5 @@ package com.mentalmachines.droidcon_boston.views.search -import android.content.DialogInterface import android.os.Bundle import android.text.Editable import android.text.TextWatcher @@ -18,21 +17,14 @@ import com.mentalmachines.droidcon_boston.utils.visibleIf /** * A full screen dialog that is used to provide searching functionality in the app. - * - * @property[queryListener] A callback that should be used to be notified of any queries made by - * this dialog. */ class SearchDialog : DialogFragment() { private var backButton: ImageView? = null private var clearButton: ImageView? = null private var searchInput: AutoCompleteTextView? = null - var queryListener: ((String) -> Unit)? = null var itemClicked: ((Schedule.ScheduleRow) -> Unit)? = null - private val currentQuery: String - get() = searchInput?.text?.toString().orEmpty() - private lateinit var viewModel: SearchViewModel override fun onCreate(savedInstanceState: Bundle?) { @@ -109,11 +101,6 @@ class SearchDialog : DialogFragment() { } }) - searchInput?.setOnEditorActionListener { _, _, _ -> - handleQuery() - true - } - searchInput?.setOnItemClickListener { _, _, position, _ -> val adapter = (searchInput?.adapter as? ScheduleSearchAdapter) val item = adapter?.getItem(position) @@ -123,25 +110,4 @@ class SearchDialog : DialogFragment() { } } } - - /** - * Notifies our [queryListener] that a query has been made and dismisses the dialog. - */ - private fun handleQuery() { - queryListener?.invoke(currentQuery) - dismiss() - } - - /** - * In general, we can just dismiss the dialog without performing a search. However, if we - * dismiss the dialog and there is no search, we should send that out so we can clear any - * current searches. - */ - override fun onDismiss(dialog: DialogInterface?) { - if (currentQuery.isEmpty()) { - handleQuery() - } else { - super.dismiss() - } - } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt index 02d5fd0..9fdb0b0 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt @@ -13,6 +13,7 @@ import timber.log.Timber class SearchViewModel : ViewModel() { private val firebaseHelper = FirebaseHelper.instance + private val conferenceYear = "2018" private val _scheduleRows = MutableLiveData>() val scheduleRows: LiveData> = _scheduleRows @@ -24,7 +25,11 @@ class SearchViewModel : ViewModel() { val key = roomSnapshot.key ?: "" val data = roomSnapshot.getValue(FirebaseDatabase.ScheduleEvent::class.java) if (data != null) { - rows.add(data.toScheduleRow(key)) + val scheduleRow = data.toScheduleRow(key) + + if (scheduleRow.date.endsWith(conferenceYear)) { + rows.add(scheduleRow) + } } } From 17dadd1bfe66a0b0f6f5e93e5f03fc1a9f2c98c7 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Tue, 5 Mar 2019 23:16:50 -0500 Subject: [PATCH 092/173] Moved date variables into build config fields for #157. --- Droidcon-Boston/app/build.gradle | 7 +++++++ .../mentalmachines/droidcon_boston/data/Schedule.kt | 2 -- .../views/agenda/AgendaDayPagerAdapter.kt | 9 ++++++++- .../droidcon_boston/views/agenda/AgendaFragment.kt | 11 ++++++----- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index 8e08f69..7a4cf46 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -23,6 +23,13 @@ android { vectorDrawables { useSupportLibrary = true } + + buildConfigField "int", "EVENT_YEAR", "2018" + buildConfigField "int", "EVENT_MONTH", "03" + buildConfigField "int", "EVENT_DAY_ONE", "26" + buildConfigField "int", "EVENT_DAY_TWO", "27" + buildConfigField "String", "EVENT_DAY_ONE_STRING", "\"03/26/2018\"" + buildConfigField "String", "EVENT_DAY_TWO_STRING", "\"03/27/2018\"" } signingConfigs { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt index a51745f..ada5036 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt @@ -55,7 +55,5 @@ class Schedule { companion object { var SCHEDULE_ITEM_ROW = "schedule_item_row" - var MONDAY = "03/26/2018" - var TUESDAY = "03/27/2018" } } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt index c6ffc56..e56986f 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayPagerAdapter.kt @@ -2,6 +2,7 @@ package com.mentalmachines.droidcon_boston.views.agenda import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager +import com.mentalmachines.droidcon_boston.BuildConfig import com.mentalmachines.droidcon_boston.data.Schedule class AgendaDayPagerAdapter internal constructor( @@ -18,9 +19,15 @@ class AgendaDayPagerAdapter internal constructor( } override fun getItem(position: Int): Fragment { + val dayString = if (position == 0) { + BuildConfig.EVENT_DAY_ONE_STRING + } else { + BuildConfig.EVENT_DAY_TWO_STRING + } + return AgendaDayFragment.newInstance( myAgenda, - if (position == 0) Schedule.MONDAY else Schedule.TUESDAY + dayString ) } diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt index 300f3d6..a36c8a3 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaFragment.kt @@ -8,6 +8,7 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import com.mentalmachines.droidcon_boston.BuildConfig import com.mentalmachines.droidcon_boston.R import kotlinx.android.synthetic.main.agenda_fragment.* import java.util.* @@ -43,7 +44,11 @@ class AgendaFragment : Fragment() { // set current day to second if today matches val today = Calendar.getInstance() val dayTwo = Calendar.getInstance() - dayTwo.set(EVENT_YEAR, EVENT_MONTH, EVENT_DAY_ONE) + dayTwo.set( + BuildConfig.EVENT_YEAR, + BuildConfig.EVENT_MONTH - 1, // Calendar is 0 indexed + BuildConfig.EVENT_DAY_TWO + ) if (today == dayTwo) { viewpager.currentItem = 1 } @@ -87,9 +92,5 @@ class AgendaFragment : Fragment() { fragment.arguments = args return fragment } - - private const val EVENT_YEAR = 2018 - private const val EVENT_MONTH = Calendar.MARCH - private const val EVENT_DAY_ONE = 27 } } From 72d604d68b103d325bb0dce2cd8a7d235f9679d1 Mon Sep 17 00:00:00 2001 From: AdamMc331 Date: Wed, 6 Mar 2019 09:06:27 -0500 Subject: [PATCH 093/173] Converted date in search page for #157. --- .../droidcon_boston/views/search/SearchViewModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt index 9fdb0b0..f972613 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/search/SearchViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModel import com.google.firebase.database.DataSnapshot import com.google.firebase.database.DatabaseError import com.google.firebase.database.ValueEventListener +import com.mentalmachines.droidcon_boston.BuildConfig import com.mentalmachines.droidcon_boston.data.FirebaseDatabase import com.mentalmachines.droidcon_boston.data.Schedule import com.mentalmachines.droidcon_boston.firebase.FirebaseHelper @@ -13,7 +14,6 @@ import timber.log.Timber class SearchViewModel : ViewModel() { private val firebaseHelper = FirebaseHelper.instance - private val conferenceYear = "2018" private val _scheduleRows = MutableLiveData>() val scheduleRows: LiveData> = _scheduleRows @@ -27,7 +27,7 @@ class SearchViewModel : ViewModel() { if (data != null) { val scheduleRow = data.toScheduleRow(key) - if (scheduleRow.date.endsWith(conferenceYear)) { + if (scheduleRow.date.endsWith(BuildConfig.EVENT_YEAR.toString())) { rows.add(scheduleRow) } } From f4bf7e840271d1d981d2c3e0ed8dd23c73f15209 Mon Sep 17 00:00:00 2001 From: amanjeetsingh150 Date: Sat, 9 Mar 2019 23:49:58 +0530 Subject: [PATCH 094/173] fix: cleaning up code and fixing the progress on fragment load --- Droidcon-Boston/app/build.gradle | 2 +- .../app/src/main/assets/dancing_droid.json | 7961 ++++++++++++++++- .../views/agenda/AgendaDayFragment.kt | 12 + .../views/agenda/ScheduleAdapterItem.kt | 49 +- .../views/detail/AgendaDetailFragment.kt | 28 +- .../main/res/layout/agenda_day_fragment.xml | 11 + .../app/src/main/res/layout/schedule_item.xml | 5 +- 7 files changed, 8011 insertions(+), 57 deletions(-) diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index 5d15dbc..9ef58ef 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -115,7 +115,7 @@ dependencies { final mockitoCore = '2.23.4' final archCore = '2.0.0' final timber = '4.7.1' - final lottieVersion = '2.8.0' + final lottieVersion = '3.0.0-beta2' //endregion //region Dependencies diff --git a/Droidcon-Boston/app/src/main/assets/dancing_droid.json b/Droidcon-Boston/app/src/main/assets/dancing_droid.json index 4da9aed..4494427 100644 --- a/Droidcon-Boston/app/src/main/assets/dancing_droid.json +++ b/Droidcon-Boston/app/src/main/assets/dancing_droid.json @@ -1 +1,7960 @@ -{"v":"5.4.3","fr":29.9700012207031,"ip":0,"op":80.0000032584668,"w":600,"h":600,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Head/Animation Android Outlines","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-0.405,"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2},"a":{"a":0,"k":[72,72,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.404,0],[0,1.403],[-1.403,0],[0,-1.404]],"o":[[-1.403,0],[0,-1.404],[1.404,0],[0,1.403]],"v":[[14.069,6.231],[11.523,3.686],[14.069,1.141],[16.615,3.686]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[1.404,0],[0,1.403],[-1.404,0],[0,-1.404]],"o":[[-1.404,0],[0,-1.404],[1.404,0],[0,1.403]],"v":[[-14.068,6.231],[-16.615,3.686],[-14.068,1.141],[-11.522,3.686]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[9.264,4.82],[0,0],[0.469,0.26],[0.159,0],[0.178,-0.319],[0,0],[4.725,0],[3.992,-1.772],[0,0],[0.469,-0.26],[-0.26,-0.468],[0,0],[0.013,-10.512],[0,0]],"o":[[0,0],[0.26,-0.468],[-0.148,-0.082],[-0.342,0],[0,0],[-3.991,-1.772],[-4.726,0],[0,0],[-0.26,-0.468],[-0.468,0.26],[0,0],[-9.264,4.82],[0,0],[-0.014,-10.512]],"v":[[14.945,-7.107],[19.766,-15.805],[19.387,-17.126],[18.919,-17.247],[18.066,-16.747],[13.191,-7.954],[0.001,-10.717],[-13.193,-7.954],[-18.066,-16.747],[-19.387,-17.126],[-19.766,-15.805],[-14.945,-7.107],[-30.481,17.385],[30.482,17.385]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[71.25,34.421],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":81.0000032991976,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Left Arm/Animation Android Outlines","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p2_1_0p333_0"],"t":0,"s":[0],"e":[-42.718]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p2_1_0p333_0"],"t":10,"s":[-42.718],"e":[45]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p2_1_0p333_0"],"t":30,"s":[45],"e":[-45]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p2_1_0p333_0"],"t":50,"s":[-45],"e":[37.875]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p2_1_0p333_0"],"t":70,"s":[37.875],"e":[0]},{"t":80.0000032584668}],"ix":10},"p":{"a":0,"k":[31.786,52.697,0],"ix":2},"a":{"a":0,"k":[31.786,52.697,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-0.383,0.026],[-0.301,-0.195],[0,0],[0,0]],"o":[[0,0],[0,0],[0.271,-0.231],[0.385,-0.027],[0,0],[0,0],[0,0]],"v":[[-6.833,-2.899],[-6.833,1.522],[0.749,5.721],[1.743,5.308],[2.788,5.583],[6.833,1.07],[6.833,-5.721]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.389,82.85],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.066,-0.004],[0.334,0.474],[2.98,-0.852],[0,0],[-0.858,-0.177],[-0.604,0.042],[-0.066,-0.942],[0.942,-0.066],[0.278,0.152],[2.067,-2.102],[0,0],[0,0],[0,0],[0,0]],"o":[[-0.62,0.043],[-1.29,0.369],[0,0],[1.619,0.338],[0.27,-0.496],[0.942,-0.066],[0.066,0.943],[-0.34,0.023],[-0.881,0.969],[0,0],[0,0],[0,0],[0,0],[-0.064,0.012]],"v":[[1.263,-9.417],[-0.251,-10.144],[-6.833,-8.262],[-6.833,-2.087],[-3.107,-1.313],[-1.727,-2.204],[0.098,-0.618],[-1.488,1.208],[-2.428,0.999],[-6.833,5.587],[-6.833,10.144],[6.833,7.321],[6.833,-3.293],[1.455,-9.45]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.389,68.913],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.102,-0.09],[0,0],[0,0],[0.007,0.132],[0,0]],"o":[[0,0],[0,0],[0,-0.132],[0,0],[-0.078,0.112]],"v":[[-2.281,-2.459],[2.281,2.763],[2.281,-1.647],[2.261,-2.041],[-2.012,-2.763]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[35.942,61.526],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.084,-0.475],[-0.001,-0.021],[0.019,-0.123],[0,0],[0,1.14],[0,0]],"o":[[0.002,0.021],[0.009,0.128],[0,0],[0.495,-0.945],[0,0],[-1.098,0.482]],"v":[[-1.634,-0.194],[-1.624,-0.134],[-1.642,0.243],[0.863,1.63],[1.642,-1.527],[1.642,-1.63]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[36.58,89.879],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.512,0.315],[0,0],[-0.862,0.945],[0.02,0.285],[0.001,0.028]],"o":[[0,0],[1.555,-1.59],[-0.14,-0.228],[-0.002,-0.028],[-0.829,-0.17]],"v":[[-1.887,-2.766],[-1.887,2.766],[1.887,-1.18],[1.633,-1.952],[1.635,-2.035]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[26.443,70.486],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":2,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.265,0.361],[0,0.013],[-0.942,0.066],[-0.066,-0.942],[0.007,-0.084],[0,0],[3.323,0],[0.077,-3.703]],"o":[[-0.001,-0.013],[-0.066,-0.942],[0.942,-0.066],[0.006,0.087],[0,0],[-0.609,-3.148],[-3.72,0],[2.812,-0.804]],"v":[[-0.495,1.554],[-0.501,1.517],[1.085,-0.308],[2.91,1.279],[2.902,1.534],[6.766,2.187],[0.06,-3.346],[-6.766,3.346]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.328,56.392],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":2,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.023,0.448],[0,0]],"o":[[1.004,-0.44],[0,0],[0,0]],"v":[[-1.522,1.699],[1.522,0.363],[1.522,-1.699]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[36.7,86.93],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 7","np":2,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.497,-0.034],[0.34,0.388],[0.544,-0.239],[-0.007,-0.102],[0.059,-0.194],[0,0],[-0.972,1.39],[0,0]],"o":[[-0.554,0.039],[-0.551,0.241],[0.024,0.095],[0.015,0.215],[0,0],[1.713,-0.369],[0,0],[-0.288,0.362]],"v":[[-0.276,-1.408],[-1.676,-1.991],[-3.319,-1.273],[-3.268,-0.978],[-3.342,-0.363],[-0.818,2.052],[3.342,-0.72],[0.937,-2.052]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[33.646,92.977],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 8","np":2,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-0.158,0.011],[-0.339,-0.35],[0,0],[0.006,0.074],[-0.075,0.214]],"o":[[0,0],[0,0],[0.141,-0.05],[0.523,-0.037],[0,0],[-0.014,-0.07],[-0.017,-0.241],[0,0]],"v":[[-3.542,-2.781],[-3.542,-1.041],[0.01,2.358],[0.456,2.259],[1.799,2.781],[3.484,2.043],[3.447,1.829],[3.542,1.142]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[28.097,88.154],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 9","np":2,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.937,-1.17],[-0.307,0.133],[-0.273,0.324],[0,0],[0,0]],"o":[[0.302,-0.131],[-0.026,-0.455],[0,0],[0,0],[0,1.612]],"v":[[0.094,2.144],[1.005,1.748],[1.406,0.547],[-1.406,-2.144],[-1.406,-2.118]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[25.962,90.469],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 10","np":2,"cix":2,"bm":0,"ix":10,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.404,-0.028],[0.337,0.331],[0,0],[-1.639,0],[-0.107,0.005],[0,0]],"o":[[-0.508,0.036],[0,0],[1.179,0.966],[0.108,0],[0,0],[-0.276,0.255]],"v":[[-0.596,-0.436],[-1.908,-0.926],[-2.321,-0.622],[2.001,0.926],[2.321,0.91],[0.44,-0.891]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[29.388,94.26],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 11","np":2,"cix":2,"bm":0,"ix":11,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":81.0000032991976,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Left Arm Background","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0.008,"ix":10},"p":{"a":0,"k":[31.786,52.697,0],"ix":2},"a":{"a":0,"k":[111.678,52.697,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.768,0],[0,-3.768],[0,0],[-3.769,0],[0,3.769],[0,0]],"o":[[-3.769,0],[0,0],[0,3.769],[3.768,0],[0,0],[0,-3.768]],"v":[[0.001,-21.07],[-6.834,-14.237],[-6.834,14.236],[0.001,21.07],[6.834,14.236],[6.834,-14.237]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.993504901961,0.993504901961,0.993504901961,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[111.111,74.116],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":81.0000032991976,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Right arm/Animation Android Outlines","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p2_1_0p333_0"],"t":0,"s":[0],"e":[-39.985]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p2_1_0p333_0"],"t":10,"s":[-39.985],"e":[45]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p2_1_0p333_0"],"t":30,"s":[45],"e":[-45]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p2_1_0p333_0"],"t":50,"s":[-45],"e":[37.875]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p2_1_0p333_0"],"t":70,"s":[37.875],"e":[0]},{"t":80.0000032584668}],"ix":10},"p":{"a":0,"k":[111.678,52.697,0],"ix":2},"a":{"a":0,"k":[111.678,52.697,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.768,0],[0,-3.768],[0,0],[-3.769,0],[0,3.769],[0,0]],"o":[[-3.769,0],[0,0],[0,3.769],[3.768,0],[0,0],[0,-3.768]],"v":[[0.001,-21.07],[-6.834,-14.237],[-6.834,14.236],[0.001,21.07],[6.834,14.236],[6.834,-14.237]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[111.111,74.116],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":81.0000032991976,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Body/Animation Android Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[298,512,0],"ix":2},"a":{"a":0,"k":[71.464,128.836,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.7,0.7,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"n":["0p7_1_0p3_0","0p7_1_0p3_0","0p667_1_0p333_0"],"t":0,"s":[373.002,373.002,100],"e":[373.002,322.075,100]},{"i":{"x":[0.7,0.7,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"n":["0p7_1_0p3_0","0p7_1_0p3_0","0p667_1_0p333_0"],"t":10,"s":[373.002,322.075,100],"e":[373.002,373.002,100]},{"i":{"x":[0.7,0.7,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"n":["0p7_1_0p3_0","0p7_1_0p3_0","0p667_1_0p333_0"],"t":20,"s":[373.002,373.002,100],"e":[373.002,322.075,100]},{"i":{"x":[0.7,0.7,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"n":["0p7_1_0p3_0","0p7_1_0p3_0","0p667_1_0p333_0"],"t":30,"s":[373.002,322.075,100],"e":[373.002,373.002,100]},{"i":{"x":[0.7,0.7,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"n":["0p7_1_0p3_0","0p7_1_0p3_0","0p667_1_0p333_0"],"t":40,"s":[373.002,373.002,100],"e":[373.002,322.075,100]},{"i":{"x":[0.7,0.7,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"n":["0p7_1_0p3_0","0p7_1_0p3_0","0p667_1_0p333_0"],"t":50,"s":[373.002,322.075,100],"e":[373.002,373.002,100]},{"i":{"x":[0.7,0.7,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"n":["0p7_1_0p3_0","0p7_1_0p3_0","0p667_1_0p333_0"],"t":60,"s":[373.002,373.002,100],"e":[373.002,322.075,100]},{"i":{"x":[0.7,0.7,0.667],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.333],"y":[0,0,0]},"n":["0p7_1_0p3_0","0p7_1_0p3_0","0p667_1_0p333_0"],"t":70,"s":[373.002,322.075,100],"e":[373.002,373.002,100]},{"t":80.0000032584668}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.437,-0.032],[0.176,0.046],[1.951,-3.071],[0,0],[-0.137,0.009],[-0.261,-0.686],[0,0],[0,0]],"o":[[-0.283,0.291],[-0.19,0.012],[-1.946,3.058],[0,0],[0.127,-0.04],[0.771,-0.054],[0,0],[0,0],[0,0]],"v":[[1.454,-7.663],[0.351,-7.144],[-0.199,-7.202],[-6.061,2.017],[-1.228,6.642],[-0.833,6.562],[0.878,7.663],[6.061,6.829],[6.061,-5.111]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[60.633,113.818],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.171,-0.012],[0.328,0.501],[0,0],[0,-0.003],[0.251,-0.322],[0,0],[0,0],[0.031,0.447],[-0.153,0.278]],"o":[[-0.152,0.058],[-0.64,0.044],[0,0],[0,0.003],[0.031,0.438],[0,0],[0,0],[-0.302,-0.285],[-0.024,-0.34],[0,0]],"v":[[-3.177,-7.667],[-3.659,-7.553],[-5.202,-8.327],[-7.928,-7.125],[-7.927,-7.116],[-8.289,-5.949],[7.537,8.327],[8.289,7.146],[7.751,6.023],[7.96,5.083]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[56.656,90.752],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.642,0.045],[-0.065,-0.943],[0.943,-0.065],[0.255,0.12],[7.649,-12.004],[-0.026,-0.358],[0.265,-0.325],[0,0],[0,0],[0,0],[0,0],[-0.094,0.007],[-0.067,-0.942],[0.806,-0.185],[0,0],[-0.186,0],[0,3.767],[0,0],[0,0],[0,4.07],[0,0],[0,0]],"o":[[0,0],[0.254,-0.543],[0.941,-0.066],[0.067,0.942],[-0.301,0.022],[-3.04,4.759],[0.208,0.261],[0.031,0.451],[0,0],[0,0],[0,0],[0,0],[0.09,-0.022],[0.942,-0.067],[0.058,0.851],[0,0],[0.182,0.015],[3.768,0],[0,0],[0,0],[4.071,0],[0,0],[0,0],[0,0]],"v":[[-30.482,-31.917],[12.62,-24.633],[14.042,-25.618],[15.867,-24.031],[14.281,-22.207],[13.439,-22.37],[-3.798,4.646],[-3.431,5.588],[-3.814,6.783],[3.21,14.822],[4.557,14.822],[4.557,16.363],[12.62,25.594],[12.893,25.547],[14.719,27.133],[13.395,28.913],[10.839,36.701],[11.389,36.729],[18.223,29.896],[18.223,14.822],[23.113,14.822],[30.482,7.452],[30.482,-36.729],[-30.482,-36.729]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[71.25,90.948],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.001,0.014],[0,0],[0,0],[-0.185,-0.619],[0,0]],"o":[[0,0],[0,0],[0,0.679],[0,0],[0.001,-0.015]],"v":[[2.596,0.249],[-2.596,-1.079],[-2.596,-0.874],[-2.31,1.079],[2.596,0.292]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[55.625,121.717],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.053,0.059],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0.044,-0.066]],"v":[[2.81,2.083],[-1.745,-2.273],[-2.81,-0.596],[-2.81,0.874],[2.668,2.273]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[55.838,118.862],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":2,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-0.21,-0.532],[-0.21,0.532],[0.21,-0.13]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[53.238,116.099],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":2,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-4.07,0],[0,0],[0,0],[0,0],[0,0],[0.03,0.434],[-0.041,0.168]],"o":[[0,0],[0,4.07],[0,0],[0,0],[0,0],[0,0],[-0.287,-0.282],[-0.013,-0.181],[0,0]],"v":[[-9.452,-10.433],[-9.452,-6.383],[-2.083,0.987],[2.809,0.987],[2.809,9.573],[3.708,10.433],[9.452,1.399],[8.941,0.303],[8.993,-0.22]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[50.22,104.784],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 7","np":2,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.304,0.021],[-0.168,-0.83],[0,0],[0,0]],"o":[[0,0],[0.237,-0.156],[0.866,-0.061],[0,0],[0,0],[0,0]],"v":[[-21.025,0.184],[-15.929,6.016],[-15.112,5.734],[-13.325,7.1],[21.025,0.007],[-21.025,-7.101]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[61.793,67.019],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 8","np":2,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.016,-0.057],[0,0],[-0.16,1.567]],"o":[[-0.009,0.06],[0,0],[1.038,-1.073],[0,0]],"v":[[-2.507,-1.213],[-2.548,-1.04],[0.656,2.025],[2.548,-2.025]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[64.112,123.564],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 9","np":2,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.204,0.412],[0,0],[0,0],[-3.083,-0.66],[0,0]],"o":[[0,0],[0,0],[0,3.277],[0,0],[-0.437,-0.141]],"v":[[2.961,-4.282],[-3.965,-3.17],[-3.965,-2.397],[1.438,4.282],[3.965,-3.416]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[79.77,123.241],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 10","np":2,"cix":2,"bm":0,"ix":10,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.068,0.169],[0,0]],"o":[[0,0],[0.011,-0.189],[0,0],[0,0]],"v":[[-3.439,2.717],[3.319,1.632],[3.439,1.092],[-3.439,-2.717]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[79.245,116.468],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 11","np":2,"cix":2,"bm":0,"ix":11,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-1.877,-1.238],[1.877,2.148],[-1.877,-2.148]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[77.683,110.791],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 12","np":2,"cix":2,"bm":0,"ix":12,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-2.898,-0.596],[2.898,2.615],[-2.898,-2.615]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[78.704,113.346],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 13","np":2,"cix":2,"bm":0,"ix":13,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.026,-0.372],[0.045,-0.174],[0,0],[0,0],[0,0]],"o":[[0,0],[0.221,0.266],[0.013,0.188],[0,0],[0,0],[0,0],[0,0]],"v":[[-1.865,-3.642],[-4.063,-0.188],[-3.669,0.785],[-3.727,1.328],[0.454,3.642],[0.454,1.707],[4.064,1.707]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[66.24,104.064],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 14","np":2,"cix":2,"bm":0,"ix":14,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.142,-0.163],[0,0],[-0.286,0.02],[-0.339,-0.344],[-8.865,3.947]],"o":[[-0.073,0.207],[0,0],[0.228,-0.141],[0.52,-0.036],[8.823,-3.897],[0,0]],"v":[[-16.289,0.758],[-16.615,1.317],[-12.717,5.779],[-11.943,5.522],[-10.607,6.036],[16.615,-6.036]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[64.702,74.266],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 15","np":2,"cix":2,"bm":0,"ix":15,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.544,0.679],[0.007,0.096],[-0.671,0.269],[0,0],[0.019,0.004]],"o":[[0,0],[1.521,-0.669],[-0.022,-0.091],[-0.053,-0.759],[0,0],[-0.02,-0.005],[0,0]],"v":[[-2.842,1.247],[-2.842,5.032],[1.756,3.01],[1.708,2.731],[2.782,1.031],[2.842,-5.019],[2.784,-5.032]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[43.61,81.144],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 16","np":2,"cix":2,"bm":0,"ix":16,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.005,0.006],[13.475,-5.953],[-0.008,-0.106],[0.268,-0.325],[0,0],[-0.284,0.02],[-0.232,-0.093],[-2.13,3.332]],"o":[[-4.034,1.798],[0.025,0.099],[0.031,0.453],[0,0],[0.226,-0.138],[0.266,-0.018],[8.246,-12.943],[-0.005,-0.006]],"v":[[14.896,-13.605],[-14.574,-0.529],[-14.521,-0.222],[-14.909,0.979],[-3.878,13.605],[-3.111,13.353],[-2.36,13.477],[14.909,-13.586]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[69.105,81.597],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 17","np":2,"cix":2,"bm":0,"ix":17,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.174,-0.012],[0.165,0.039],[0,0],[0,0],[0,0],[0,0]],"o":[[-0.177,0.013],[0,0],[0,0],[0,0],[0,0],[-0.155,0.059]],"v":[[-2.842,-3.646],[-3.355,-3.697],[-4.222,-2.335],[2.536,3.763],[4.221,3.763],[-2.353,-3.762]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[69.074,102.008],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 18","np":2,"cix":2,"bm":0,"ix":18,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.007,-0.003],[0,0],[-0.266,-0.392],[0,0],[-0.147,0.27],[0,0]],"o":[[0,0],[0.482,0.07],[0,0],[-0.019,-0.329],[0,0],[-0.007,0.003]],"v":[[-1.995,-3.357],[-2.055,2.63],[-0.889,3.365],[1.85,2.158],[2.055,1.245],[-1.973,-3.366]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[49.323,79.436],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 19","np":2,"cix":2,"bm":0,"ix":19,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.421,-0.03],[0.303,0.59],[0,0],[-2.773,0],[-1.169,0.935]],"o":[[-0.28,0.274],[-0.704,0.049],[0,0],[1.069,2.38],[1.61,0],[0,0]],"v":[[2.236,-1.969],[1.165,-1.48],[-0.475,-2.406],[-5.245,-1.639],[0.986,2.406],[5.245,0.909]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[58.874,125.271],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 20","np":2,"cix":2,"bm":0,"ix":20,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.339,0.358],[1.668,-0.733],[0,0],[0,0],[-0.444,0.031],[-0.222,-0.083],[0,0],[0,0],[0.181,-0.013]],"o":[[-1.674,0.736],[0,0],[0,0],[0.284,-0.299],[0.252,-0.018],[0,0],[0,0],[-0.16,0.064],[-0.531,0.037]],"v":[[-6.456,-9.434],[-11.474,-7.227],[-11.474,-1.009],[7.387,9.435],[8.504,8.903],[9.219,9.01],[11.474,5.467],[-4.59,-9.021],[-5.099,-8.897]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[52.242,94.359],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 21","np":2,"cix":2,"bm":0,"ix":21,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0.006,0.08],[-0.133,0.264]],"o":[[0,0],[0,0],[-0.016,-0.076],[-0.022,-0.316],[0,0]],"v":[[-2.254,-3.587],[-2.254,3.587],[2.112,2.686],[2.072,2.455],[2.254,1.575]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[43.022,72.122],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 22","np":2,"cix":2,"bm":0,"ix":22,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0.018,0.02]],"o":[[0,0],[0,0],[-0.02,-0.019],[0,0]],"v":[[-2.421,-1.745],[-2.421,2.732],[2.421,-2.671],[2.363,-2.732]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.437971646178,0.744312720205,0.222755297493,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[43.189,78.347],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 23","np":2,"cix":2,"bm":0,"ix":23,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":81.0000032991976,"st":0,"bm":0}],"markers":[]} \ No newline at end of file +{ + "v": "5.4.3", + "fr": 29.9700012207031, + "ip": 0, + "op": 80.0000032584668, + "w": 600, + "h": 600, + "nm": "Comp 1", + "ddd": 0, + "assets": [], + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "Head/Animation Android Outlines", + "parent": 5, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": -0.405, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 72, + 72, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 72, + 72, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 1.404, + 0 + ], + [ + 0, + 1.403 + ], + [ + -1.403, + 0 + ], + [ + 0, + -1.404 + ] + ], + "o": [ + [ + -1.403, + 0 + ], + [ + 0, + -1.404 + ], + [ + 1.404, + 0 + ], + [ + 0, + 1.403 + ] + ], + "v": [ + [ + 14.069, + 6.231 + ], + [ + 11.523, + 3.686 + ], + [ + 14.069, + 1.141 + ], + [ + 16.615, + 3.686 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ind": 1, + "ty": "sh", + "ix": 2, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 1.404, + 0 + ], + [ + 0, + 1.403 + ], + [ + -1.404, + 0 + ], + [ + 0, + -1.404 + ] + ], + "o": [ + [ + -1.404, + 0 + ], + [ + 0, + -1.404 + ], + [ + 1.404, + 0 + ], + [ + 0, + 1.403 + ] + ], + "v": [ + [ + -14.068, + 6.231 + ], + [ + -16.615, + 3.686 + ], + [ + -14.068, + 1.141 + ], + [ + -11.522, + 3.686 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 2", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ind": 2, + "ty": "sh", + "ix": 3, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 9.264, + 4.82 + ], + [ + 0, + 0 + ], + [ + 0.469, + 0.26 + ], + [ + 0.159, + 0 + ], + [ + 0.178, + -0.319 + ], + [ + 0, + 0 + ], + [ + 4.725, + 0 + ], + [ + 3.992, + -1.772 + ], + [ + 0, + 0 + ], + [ + 0.469, + -0.26 + ], + [ + -0.26, + -0.468 + ], + [ + 0, + 0 + ], + [ + 0.013, + -10.512 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0.26, + -0.468 + ], + [ + -0.148, + -0.082 + ], + [ + -0.342, + 0 + ], + [ + 0, + 0 + ], + [ + -3.991, + -1.772 + ], + [ + -4.726, + 0 + ], + [ + 0, + 0 + ], + [ + -0.26, + -0.468 + ], + [ + -0.468, + 0.26 + ], + [ + 0, + 0 + ], + [ + -9.264, + 4.82 + ], + [ + 0, + 0 + ], + [ + -0.014, + -10.512 + ] + ], + "v": [ + [ + 14.945, + -7.107 + ], + [ + 19.766, + -15.805 + ], + [ + 19.387, + -17.126 + ], + [ + 18.919, + -17.247 + ], + [ + 18.066, + -16.747 + ], + [ + 13.191, + -7.954 + ], + [ + 0.001, + -10.717 + ], + [ + -13.193, + -7.954 + ], + [ + -18.066, + -16.747 + ], + [ + -19.387, + -17.126 + ], + [ + -19.766, + -15.805 + ], + [ + -14.945, + -7.107 + ], + [ + -30.481, + 17.385 + ], + [ + 30.482, + 17.385 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 3", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "mm", + "mm": 1, + "nm": "Merge Paths 1", + "mn": "ADBE Vector Filter - Merge", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 71.25, + 34.421 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 5, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 81.0000032991976, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 2, + "ty": 4, + "nm": "Left Arm/Animation Android Outlines", + "parent": 5, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.2 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p2_1_0p333_0" + ], + "t": 0, + "s": [ + 0 + ], + "e": [ + -42.718 + ] + }, + { + "i": { + "x": [ + 0.2 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p2_1_0p333_0" + ], + "t": 10, + "s": [ + -42.718 + ], + "e": [ + 45 + ] + }, + { + "i": { + "x": [ + 0.2 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p2_1_0p333_0" + ], + "t": 30, + "s": [ + 45 + ], + "e": [ + -45 + ] + }, + { + "i": { + "x": [ + 0.2 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p2_1_0p333_0" + ], + "t": 50, + "s": [ + -45 + ], + "e": [ + 37.875 + ] + }, + { + "i": { + "x": [ + 0.2 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p2_1_0p333_0" + ], + "t": 70, + "s": [ + 37.875 + ], + "e": [ + 0 + ] + }, + { + "t": 80.0000032584668 + } + ], + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 31.786, + 52.697, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 31.786, + 52.697, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.383, + 0.026 + ], + [ + -0.301, + -0.195 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.271, + -0.231 + ], + [ + 0.385, + -0.027 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -6.833, + -2.899 + ], + [ + -6.833, + 1.522 + ], + [ + 0.749, + 5.721 + ], + [ + 1.743, + 5.308 + ], + [ + 2.788, + 5.583 + ], + [ + 6.833, + 1.07 + ], + [ + 6.833, + -5.721 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 31.389, + 82.85 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.066, + -0.004 + ], + [ + 0.334, + 0.474 + ], + [ + 2.98, + -0.852 + ], + [ + 0, + 0 + ], + [ + -0.858, + -0.177 + ], + [ + -0.604, + 0.042 + ], + [ + -0.066, + -0.942 + ], + [ + 0.942, + -0.066 + ], + [ + 0.278, + 0.152 + ], + [ + 2.067, + -2.102 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + -0.62, + 0.043 + ], + [ + -1.29, + 0.369 + ], + [ + 0, + 0 + ], + [ + 1.619, + 0.338 + ], + [ + 0.27, + -0.496 + ], + [ + 0.942, + -0.066 + ], + [ + 0.066, + 0.943 + ], + [ + -0.34, + 0.023 + ], + [ + -0.881, + 0.969 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.064, + 0.012 + ] + ], + "v": [ + [ + 1.263, + -9.417 + ], + [ + -0.251, + -10.144 + ], + [ + -6.833, + -8.262 + ], + [ + -6.833, + -2.087 + ], + [ + -3.107, + -1.313 + ], + [ + -1.727, + -2.204 + ], + [ + 0.098, + -0.618 + ], + [ + -1.488, + 1.208 + ], + [ + -2.428, + 0.999 + ], + [ + -6.833, + 5.587 + ], + [ + -6.833, + 10.144 + ], + [ + 6.833, + 7.321 + ], + [ + 6.833, + -3.293 + ], + [ + 1.455, + -9.45 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 31.389, + 68.913 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 2", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 2, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.102, + -0.09 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.007, + 0.132 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -0.132 + ], + [ + 0, + 0 + ], + [ + -0.078, + 0.112 + ] + ], + "v": [ + [ + -2.281, + -2.459 + ], + [ + 2.281, + 2.763 + ], + [ + 2.281, + -1.647 + ], + [ + 2.261, + -2.041 + ], + [ + -2.012, + -2.763 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 35.942, + 61.526 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 3", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 3, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 1.084, + -0.475 + ], + [ + -0.001, + -0.021 + ], + [ + 0.019, + -0.123 + ], + [ + 0, + 0 + ], + [ + 0, + 1.14 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0.002, + 0.021 + ], + [ + 0.009, + 0.128 + ], + [ + 0, + 0 + ], + [ + 0.495, + -0.945 + ], + [ + 0, + 0 + ], + [ + -1.098, + 0.482 + ] + ], + "v": [ + [ + -1.634, + -0.194 + ], + [ + -1.624, + -0.134 + ], + [ + -1.642, + 0.243 + ], + [ + 0.863, + 1.63 + ], + [ + 1.642, + -1.527 + ], + [ + 1.642, + -1.63 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 36.58, + 89.879 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 4", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 4, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 1.512, + 0.315 + ], + [ + 0, + 0 + ], + [ + -0.862, + 0.945 + ], + [ + 0.02, + 0.285 + ], + [ + 0.001, + 0.028 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 1.555, + -1.59 + ], + [ + -0.14, + -0.228 + ], + [ + -0.002, + -0.028 + ], + [ + -0.829, + -0.17 + ] + ], + "v": [ + [ + -1.887, + -2.766 + ], + [ + -1.887, + 2.766 + ], + [ + 1.887, + -1.18 + ], + [ + 1.633, + -1.952 + ], + [ + 1.635, + -2.035 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 26.443, + 70.486 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 5", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 5, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + -1.265, + 0.361 + ], + [ + 0, + 0.013 + ], + [ + -0.942, + 0.066 + ], + [ + -0.066, + -0.942 + ], + [ + 0.007, + -0.084 + ], + [ + 0, + 0 + ], + [ + 3.323, + 0 + ], + [ + 0.077, + -3.703 + ] + ], + "o": [ + [ + -0.001, + -0.013 + ], + [ + -0.066, + -0.942 + ], + [ + 0.942, + -0.066 + ], + [ + 0.006, + 0.087 + ], + [ + 0, + 0 + ], + [ + -0.609, + -3.148 + ], + [ + -3.72, + 0 + ], + [ + 2.812, + -0.804 + ] + ], + "v": [ + [ + -0.495, + 1.554 + ], + [ + -0.501, + 1.517 + ], + [ + 1.085, + -0.308 + ], + [ + 2.91, + 1.279 + ], + [ + 2.902, + 1.534 + ], + [ + 6.766, + 2.187 + ], + [ + 0.06, + -3.346 + ], + [ + -6.766, + 3.346 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 31.328, + 56.392 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 6", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 6, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + -1.023, + 0.448 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 1.004, + -0.44 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -1.522, + 1.699 + ], + [ + 1.522, + 0.363 + ], + [ + 1.522, + -1.699 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 36.7, + 86.93 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 7", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 7, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.497, + -0.034 + ], + [ + 0.34, + 0.388 + ], + [ + 0.544, + -0.239 + ], + [ + -0.007, + -0.102 + ], + [ + 0.059, + -0.194 + ], + [ + 0, + 0 + ], + [ + -0.972, + 1.39 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + -0.554, + 0.039 + ], + [ + -0.551, + 0.241 + ], + [ + 0.024, + 0.095 + ], + [ + 0.015, + 0.215 + ], + [ + 0, + 0 + ], + [ + 1.713, + -0.369 + ], + [ + 0, + 0 + ], + [ + -0.288, + 0.362 + ] + ], + "v": [ + [ + -0.276, + -1.408 + ], + [ + -1.676, + -1.991 + ], + [ + -3.319, + -1.273 + ], + [ + -3.268, + -0.978 + ], + [ + -3.342, + -0.363 + ], + [ + -0.818, + 2.052 + ], + [ + 3.342, + -0.72 + ], + [ + 0.937, + -2.052 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 33.646, + 92.977 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 8", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 8, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.158, + 0.011 + ], + [ + -0.339, + -0.35 + ], + [ + 0, + 0 + ], + [ + 0.006, + 0.074 + ], + [ + -0.075, + 0.214 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.141, + -0.05 + ], + [ + 0.523, + -0.037 + ], + [ + 0, + 0 + ], + [ + -0.014, + -0.07 + ], + [ + -0.017, + -0.241 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -3.542, + -2.781 + ], + [ + -3.542, + -1.041 + ], + [ + 0.01, + 2.358 + ], + [ + 0.456, + 2.259 + ], + [ + 1.799, + 2.781 + ], + [ + 3.484, + 2.043 + ], + [ + 3.447, + 1.829 + ], + [ + 3.542, + 1.142 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 28.097, + 88.154 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 9", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 9, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + -0.937, + -1.17 + ], + [ + -0.307, + 0.133 + ], + [ + -0.273, + 0.324 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0.302, + -0.131 + ], + [ + -0.026, + -0.455 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 1.612 + ] + ], + "v": [ + [ + 0.094, + 2.144 + ], + [ + 1.005, + 1.748 + ], + [ + 1.406, + 0.547 + ], + [ + -1.406, + -2.144 + ], + [ + -1.406, + -2.118 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 25.962, + 90.469 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 10", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 10, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.404, + -0.028 + ], + [ + 0.337, + 0.331 + ], + [ + 0, + 0 + ], + [ + -1.639, + 0 + ], + [ + -0.107, + 0.005 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + -0.508, + 0.036 + ], + [ + 0, + 0 + ], + [ + 1.179, + 0.966 + ], + [ + 0.108, + 0 + ], + [ + 0, + 0 + ], + [ + -0.276, + 0.255 + ] + ], + "v": [ + [ + -0.596, + -0.436 + ], + [ + -1.908, + -0.926 + ], + [ + -2.321, + -0.622 + ], + [ + 2.001, + 0.926 + ], + [ + 2.321, + 0.91 + ], + [ + 0.44, + -0.891 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 29.388, + 94.26 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 11", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 11, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 81.0000032991976, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 3, + "ty": 4, + "nm": "Left Arm Background", + "parent": 2, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0.008, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 31.786, + 52.697, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 111.678, + 52.697, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 3.768, + 0 + ], + [ + 0, + -3.768 + ], + [ + 0, + 0 + ], + [ + -3.769, + 0 + ], + [ + 0, + 3.769 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + -3.769, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 3.769 + ], + [ + 3.768, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -3.768 + ] + ], + "v": [ + [ + 0.001, + -21.07 + ], + [ + -6.834, + -14.237 + ], + [ + -6.834, + 14.236 + ], + [ + 0.001, + 21.07 + ], + [ + 6.834, + 14.236 + ], + [ + 6.834, + -14.237 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.993504901961, + 0.993504901961, + 0.993504901961, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 111.111, + 74.116 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 81.0000032991976, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 4, + "ty": 4, + "nm": "Right arm/Animation Android Outlines", + "parent": 5, + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.2 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p2_1_0p333_0" + ], + "t": 0, + "s": [ + 0 + ], + "e": [ + -39.985 + ] + }, + { + "i": { + "x": [ + 0.2 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p2_1_0p333_0" + ], + "t": 10, + "s": [ + -39.985 + ], + "e": [ + 45 + ] + }, + { + "i": { + "x": [ + 0.2 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p2_1_0p333_0" + ], + "t": 30, + "s": [ + 45 + ], + "e": [ + -45 + ] + }, + { + "i": { + "x": [ + 0.2 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p2_1_0p333_0" + ], + "t": 50, + "s": [ + -45 + ], + "e": [ + 37.875 + ] + }, + { + "i": { + "x": [ + 0.2 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p2_1_0p333_0" + ], + "t": 70, + "s": [ + 37.875 + ], + "e": [ + 0 + ] + }, + { + "t": 80.0000032584668 + } + ], + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 111.678, + 52.697, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 111.678, + 52.697, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 3.768, + 0 + ], + [ + 0, + -3.768 + ], + [ + 0, + 0 + ], + [ + -3.769, + 0 + ], + [ + 0, + 3.769 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + -3.769, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 3.769 + ], + [ + 3.768, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + -3.768 + ] + ], + "v": [ + [ + 0.001, + -21.07 + ], + [ + -6.834, + -14.237 + ], + [ + -6.834, + 14.236 + ], + [ + 0.001, + 21.07 + ], + [ + 6.834, + 14.236 + ], + [ + 6.834, + -14.237 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 111.111, + 74.116 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 81.0000032991976, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 5, + "ty": 4, + "nm": "Body/Animation Android Outlines", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 298, + 512, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 71.464, + 128.836, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.7, + 0.7, + 0.667 + ], + "y": [ + 1, + 1, + 1 + ] + }, + "o": { + "x": [ + 0.3, + 0.3, + 0.333 + ], + "y": [ + 0, + 0, + 0 + ] + }, + "n": [ + "0p7_1_0p3_0", + "0p7_1_0p3_0", + "0p667_1_0p333_0" + ], + "t": 0, + "s": [ + 373.002, + 373.002, + 100 + ], + "e": [ + 373.002, + 322.075, + 100 + ] + }, + { + "i": { + "x": [ + 0.7, + 0.7, + 0.667 + ], + "y": [ + 1, + 1, + 1 + ] + }, + "o": { + "x": [ + 0.3, + 0.3, + 0.333 + ], + "y": [ + 0, + 0, + 0 + ] + }, + "n": [ + "0p7_1_0p3_0", + "0p7_1_0p3_0", + "0p667_1_0p333_0" + ], + "t": 10, + "s": [ + 373.002, + 322.075, + 100 + ], + "e": [ + 373.002, + 373.002, + 100 + ] + }, + { + "i": { + "x": [ + 0.7, + 0.7, + 0.667 + ], + "y": [ + 1, + 1, + 1 + ] + }, + "o": { + "x": [ + 0.3, + 0.3, + 0.333 + ], + "y": [ + 0, + 0, + 0 + ] + }, + "n": [ + "0p7_1_0p3_0", + "0p7_1_0p3_0", + "0p667_1_0p333_0" + ], + "t": 20, + "s": [ + 373.002, + 373.002, + 100 + ], + "e": [ + 373.002, + 322.075, + 100 + ] + }, + { + "i": { + "x": [ + 0.7, + 0.7, + 0.667 + ], + "y": [ + 1, + 1, + 1 + ] + }, + "o": { + "x": [ + 0.3, + 0.3, + 0.333 + ], + "y": [ + 0, + 0, + 0 + ] + }, + "n": [ + "0p7_1_0p3_0", + "0p7_1_0p3_0", + "0p667_1_0p333_0" + ], + "t": 30, + "s": [ + 373.002, + 322.075, + 100 + ], + "e": [ + 373.002, + 373.002, + 100 + ] + }, + { + "i": { + "x": [ + 0.7, + 0.7, + 0.667 + ], + "y": [ + 1, + 1, + 1 + ] + }, + "o": { + "x": [ + 0.3, + 0.3, + 0.333 + ], + "y": [ + 0, + 0, + 0 + ] + }, + "n": [ + "0p7_1_0p3_0", + "0p7_1_0p3_0", + "0p667_1_0p333_0" + ], + "t": 40, + "s": [ + 373.002, + 373.002, + 100 + ], + "e": [ + 373.002, + 322.075, + 100 + ] + }, + { + "i": { + "x": [ + 0.7, + 0.7, + 0.667 + ], + "y": [ + 1, + 1, + 1 + ] + }, + "o": { + "x": [ + 0.3, + 0.3, + 0.333 + ], + "y": [ + 0, + 0, + 0 + ] + }, + "n": [ + "0p7_1_0p3_0", + "0p7_1_0p3_0", + "0p667_1_0p333_0" + ], + "t": 50, + "s": [ + 373.002, + 322.075, + 100 + ], + "e": [ + 373.002, + 373.002, + 100 + ] + }, + { + "i": { + "x": [ + 0.7, + 0.7, + 0.667 + ], + "y": [ + 1, + 1, + 1 + ] + }, + "o": { + "x": [ + 0.3, + 0.3, + 0.333 + ], + "y": [ + 0, + 0, + 0 + ] + }, + "n": [ + "0p7_1_0p3_0", + "0p7_1_0p3_0", + "0p667_1_0p333_0" + ], + "t": 60, + "s": [ + 373.002, + 373.002, + 100 + ], + "e": [ + 373.002, + 322.075, + 100 + ] + }, + { + "i": { + "x": [ + 0.7, + 0.7, + 0.667 + ], + "y": [ + 1, + 1, + 1 + ] + }, + "o": { + "x": [ + 0.3, + 0.3, + 0.333 + ], + "y": [ + 0, + 0, + 0 + ] + }, + "n": [ + "0p7_1_0p3_0", + "0p7_1_0p3_0", + "0p667_1_0p333_0" + ], + "t": 70, + "s": [ + 373.002, + 322.075, + 100 + ], + "e": [ + 373.002, + 373.002, + 100 + ] + }, + { + "t": 80.0000032584668 + } + ], + "ix": 6 + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0.437, + -0.032 + ], + [ + 0.176, + 0.046 + ], + [ + 1.951, + -3.071 + ], + [ + 0, + 0 + ], + [ + -0.137, + 0.009 + ], + [ + -0.261, + -0.686 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + -0.283, + 0.291 + ], + [ + -0.19, + 0.012 + ], + [ + -1.946, + 3.058 + ], + [ + 0, + 0 + ], + [ + 0.127, + -0.04 + ], + [ + 0.771, + -0.054 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 1.454, + -7.663 + ], + [ + 0.351, + -7.144 + ], + [ + -0.199, + -7.202 + ], + [ + -6.061, + 2.017 + ], + [ + -1.228, + 6.642 + ], + [ + -0.833, + 6.562 + ], + [ + 0.878, + 7.663 + ], + [ + 6.061, + 6.829 + ], + [ + 6.061, + -5.111 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 60.633, + 113.818 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0.171, + -0.012 + ], + [ + 0.328, + 0.501 + ], + [ + 0, + 0 + ], + [ + 0, + -0.003 + ], + [ + 0.251, + -0.322 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.031, + 0.447 + ], + [ + -0.153, + 0.278 + ] + ], + "o": [ + [ + -0.152, + 0.058 + ], + [ + -0.64, + 0.044 + ], + [ + 0, + 0 + ], + [ + 0, + 0.003 + ], + [ + 0.031, + 0.438 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.302, + -0.285 + ], + [ + -0.024, + -0.34 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -3.177, + -7.667 + ], + [ + -3.659, + -7.553 + ], + [ + -5.202, + -8.327 + ], + [ + -7.928, + -7.125 + ], + [ + -7.927, + -7.116 + ], + [ + -8.289, + -5.949 + ], + [ + 7.537, + 8.327 + ], + [ + 8.289, + 7.146 + ], + [ + 7.751, + 6.023 + ], + [ + 7.96, + 5.083 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 56.656, + 90.752 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 2", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 2, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.642, + 0.045 + ], + [ + -0.065, + -0.943 + ], + [ + 0.943, + -0.065 + ], + [ + 0.255, + 0.12 + ], + [ + 7.649, + -12.004 + ], + [ + -0.026, + -0.358 + ], + [ + 0.265, + -0.325 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.094, + 0.007 + ], + [ + -0.067, + -0.942 + ], + [ + 0.806, + -0.185 + ], + [ + 0, + 0 + ], + [ + -0.186, + 0 + ], + [ + 0, + 3.767 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 4.07 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0.254, + -0.543 + ], + [ + 0.941, + -0.066 + ], + [ + 0.067, + 0.942 + ], + [ + -0.301, + 0.022 + ], + [ + -3.04, + 4.759 + ], + [ + 0.208, + 0.261 + ], + [ + 0.031, + 0.451 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.09, + -0.022 + ], + [ + 0.942, + -0.067 + ], + [ + 0.058, + 0.851 + ], + [ + 0, + 0 + ], + [ + 0.182, + 0.015 + ], + [ + 3.768, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 4.071, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -30.482, + -31.917 + ], + [ + 12.62, + -24.633 + ], + [ + 14.042, + -25.618 + ], + [ + 15.867, + -24.031 + ], + [ + 14.281, + -22.207 + ], + [ + 13.439, + -22.37 + ], + [ + -3.798, + 4.646 + ], + [ + -3.431, + 5.588 + ], + [ + -3.814, + 6.783 + ], + [ + 3.21, + 14.822 + ], + [ + 4.557, + 14.822 + ], + [ + 4.557, + 16.363 + ], + [ + 12.62, + 25.594 + ], + [ + 12.893, + 25.547 + ], + [ + 14.719, + 27.133 + ], + [ + 13.395, + 28.913 + ], + [ + 10.839, + 36.701 + ], + [ + 11.389, + 36.729 + ], + [ + 18.223, + 29.896 + ], + [ + 18.223, + 14.822 + ], + [ + 23.113, + 14.822 + ], + [ + 30.482, + 7.452 + ], + [ + 30.482, + -36.729 + ], + [ + -30.482, + -36.729 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 71.25, + 90.948 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 3", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 3, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + -0.001, + 0.014 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.185, + -0.619 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0.679 + ], + [ + 0, + 0 + ], + [ + 0.001, + -0.015 + ] + ], + "v": [ + [ + 2.596, + 0.249 + ], + [ + -2.596, + -1.079 + ], + [ + -2.596, + -0.874 + ], + [ + -2.31, + 1.079 + ], + [ + 2.596, + 0.292 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 55.625, + 121.717 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 4", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 4, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + -0.053, + 0.059 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.044, + -0.066 + ] + ], + "v": [ + [ + 2.81, + 2.083 + ], + [ + -1.745, + -2.273 + ], + [ + -2.81, + -0.596 + ], + [ + -2.81, + 0.874 + ], + [ + 2.668, + 2.273 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 55.838, + 118.862 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 5", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 5, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -0.21, + -0.532 + ], + [ + -0.21, + 0.532 + ], + [ + 0.21, + -0.13 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 53.238, + 116.099 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 6", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 6, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -4.07, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.03, + 0.434 + ], + [ + -0.041, + 0.168 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 4.07 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.287, + -0.282 + ], + [ + -0.013, + -0.181 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -9.452, + -10.433 + ], + [ + -9.452, + -6.383 + ], + [ + -2.083, + 0.987 + ], + [ + 2.809, + 0.987 + ], + [ + 2.809, + 9.573 + ], + [ + 3.708, + 10.433 + ], + [ + 9.452, + 1.399 + ], + [ + 8.941, + 0.303 + ], + [ + 8.993, + -0.22 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 50.22, + 104.784 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 7", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 7, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.304, + 0.021 + ], + [ + -0.168, + -0.83 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0.237, + -0.156 + ], + [ + 0.866, + -0.061 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -21.025, + 0.184 + ], + [ + -15.929, + 6.016 + ], + [ + -15.112, + 5.734 + ], + [ + -13.325, + 7.1 + ], + [ + 21.025, + 0.007 + ], + [ + -21.025, + -7.101 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 61.793, + 67.019 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 8", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 8, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0.016, + -0.057 + ], + [ + 0, + 0 + ], + [ + -0.16, + 1.567 + ] + ], + "o": [ + [ + -0.009, + 0.06 + ], + [ + 0, + 0 + ], + [ + 1.038, + -1.073 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -2.507, + -1.213 + ], + [ + -2.548, + -1.04 + ], + [ + 0.656, + 2.025 + ], + [ + 2.548, + -2.025 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 64.112, + 123.564 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 9", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 9, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.204, + 0.412 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -3.083, + -0.66 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 3.277 + ], + [ + 0, + 0 + ], + [ + -0.437, + -0.141 + ] + ], + "v": [ + [ + 2.961, + -4.282 + ], + [ + -3.965, + -3.17 + ], + [ + -3.965, + -2.397 + ], + [ + 1.438, + 4.282 + ], + [ + 3.965, + -3.416 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 79.77, + 123.241 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 10", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 10, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.068, + 0.169 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0.011, + -0.189 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -3.439, + 2.717 + ], + [ + 3.319, + 1.632 + ], + [ + 3.439, + 1.092 + ], + [ + -3.439, + -2.717 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 79.245, + 116.468 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 11", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 11, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -1.877, + -1.238 + ], + [ + 1.877, + 2.148 + ], + [ + -1.877, + -2.148 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 77.683, + 110.791 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 12", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 12, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -2.898, + -0.596 + ], + [ + 2.898, + 2.615 + ], + [ + -2.898, + -2.615 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 78.704, + 113.346 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 13", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 13, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.026, + -0.372 + ], + [ + 0.045, + -0.174 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0.221, + 0.266 + ], + [ + 0.013, + 0.188 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -1.865, + -3.642 + ], + [ + -4.063, + -0.188 + ], + [ + -3.669, + 0.785 + ], + [ + -3.727, + 1.328 + ], + [ + 0.454, + 3.642 + ], + [ + 0.454, + 1.707 + ], + [ + 4.064, + 1.707 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 66.24, + 104.064 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 14", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 14, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0.142, + -0.163 + ], + [ + 0, + 0 + ], + [ + -0.286, + 0.02 + ], + [ + -0.339, + -0.344 + ], + [ + -8.865, + 3.947 + ] + ], + "o": [ + [ + -0.073, + 0.207 + ], + [ + 0, + 0 + ], + [ + 0.228, + -0.141 + ], + [ + 0.52, + -0.036 + ], + [ + 8.823, + -3.897 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -16.289, + 0.758 + ], + [ + -16.615, + 1.317 + ], + [ + -12.717, + 5.779 + ], + [ + -11.943, + 5.522 + ], + [ + -10.607, + 6.036 + ], + [ + 16.615, + -6.036 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 64.702, + 74.266 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 15", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 15, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -1.544, + 0.679 + ], + [ + 0.007, + 0.096 + ], + [ + -0.671, + 0.269 + ], + [ + 0, + 0 + ], + [ + 0.019, + 0.004 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 1.521, + -0.669 + ], + [ + -0.022, + -0.091 + ], + [ + -0.053, + -0.759 + ], + [ + 0, + 0 + ], + [ + -0.02, + -0.005 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -2.842, + 1.247 + ], + [ + -2.842, + 5.032 + ], + [ + 1.756, + 3.01 + ], + [ + 1.708, + 2.731 + ], + [ + 2.782, + 1.031 + ], + [ + 2.842, + -5.019 + ], + [ + 2.784, + -5.032 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 43.61, + 81.144 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 16", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 16, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.005, + 0.006 + ], + [ + 13.475, + -5.953 + ], + [ + -0.008, + -0.106 + ], + [ + 0.268, + -0.325 + ], + [ + 0, + 0 + ], + [ + -0.284, + 0.02 + ], + [ + -0.232, + -0.093 + ], + [ + -2.13, + 3.332 + ] + ], + "o": [ + [ + -4.034, + 1.798 + ], + [ + 0.025, + 0.099 + ], + [ + 0.031, + 0.453 + ], + [ + 0, + 0 + ], + [ + 0.226, + -0.138 + ], + [ + 0.266, + -0.018 + ], + [ + 8.246, + -12.943 + ], + [ + -0.005, + -0.006 + ] + ], + "v": [ + [ + 14.896, + -13.605 + ], + [ + -14.574, + -0.529 + ], + [ + -14.521, + -0.222 + ], + [ + -14.909, + 0.979 + ], + [ + -3.878, + 13.605 + ], + [ + -3.111, + 13.353 + ], + [ + -2.36, + 13.477 + ], + [ + 14.909, + -13.586 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 69.105, + 81.597 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 17", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 17, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.174, + -0.012 + ], + [ + 0.165, + 0.039 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + -0.177, + 0.013 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.155, + 0.059 + ] + ], + "v": [ + [ + -2.842, + -3.646 + ], + [ + -3.355, + -3.697 + ], + [ + -4.222, + -2.335 + ], + [ + 2.536, + 3.763 + ], + [ + 4.221, + 3.763 + ], + [ + -2.353, + -3.762 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 69.074, + 102.008 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 18", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 18, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.007, + -0.003 + ], + [ + 0, + 0 + ], + [ + -0.266, + -0.392 + ], + [ + 0, + 0 + ], + [ + -0.147, + 0.27 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0.482, + 0.07 + ], + [ + 0, + 0 + ], + [ + -0.019, + -0.329 + ], + [ + 0, + 0 + ], + [ + -0.007, + 0.003 + ] + ], + "v": [ + [ + -1.995, + -3.357 + ], + [ + -2.055, + 2.63 + ], + [ + -0.889, + 3.365 + ], + [ + 1.85, + 2.158 + ], + [ + 2.055, + 1.245 + ], + [ + -1.973, + -3.366 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 49.323, + 79.436 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 19", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 19, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0.421, + -0.03 + ], + [ + 0.303, + 0.59 + ], + [ + 0, + 0 + ], + [ + -2.773, + 0 + ], + [ + -1.169, + 0.935 + ] + ], + "o": [ + [ + -0.28, + 0.274 + ], + [ + -0.704, + 0.049 + ], + [ + 0, + 0 + ], + [ + 1.069, + 2.38 + ], + [ + 1.61, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + 2.236, + -1.969 + ], + [ + 1.165, + -1.48 + ], + [ + -0.475, + -2.406 + ], + [ + -5.245, + -1.639 + ], + [ + 0.986, + 2.406 + ], + [ + 5.245, + 0.909 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 58.874, + 125.271 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 20", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 20, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0.339, + 0.358 + ], + [ + 1.668, + -0.733 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.444, + 0.031 + ], + [ + -0.222, + -0.083 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.181, + -0.013 + ] + ], + "o": [ + [ + -1.674, + 0.736 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.284, + -0.299 + ], + [ + 0.252, + -0.018 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.16, + 0.064 + ], + [ + -0.531, + 0.037 + ] + ], + "v": [ + [ + -6.456, + -9.434 + ], + [ + -11.474, + -7.227 + ], + [ + -11.474, + -1.009 + ], + [ + 7.387, + 9.435 + ], + [ + 8.504, + 8.903 + ], + [ + 9.219, + 9.01 + ], + [ + 11.474, + 5.467 + ], + [ + -4.59, + -9.021 + ], + [ + -5.099, + -8.897 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 52.242, + 94.359 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 21", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 21, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.006, + 0.08 + ], + [ + -0.133, + 0.264 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.016, + -0.076 + ], + [ + -0.022, + -0.316 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -2.254, + -3.587 + ], + [ + -2.254, + 3.587 + ], + [ + 2.112, + 2.686 + ], + [ + 2.072, + 2.455 + ], + [ + 2.254, + 1.575 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 43.022, + 72.122 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 22", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 22, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "gr", + "it": [ + { + "ind": 0, + "ty": "sh", + "ix": 1, + "ks": { + "a": 0, + "k": { + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0.018, + 0.02 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -0.02, + -0.019 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -2.421, + -1.745 + ], + [ + -2.421, + 2.732 + ], + [ + 2.421, + -2.671 + ], + [ + 2.363, + -2.732 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0.437971646178, + 0.744312720205, + 0.222755297493, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 43.189, + 78.347 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 23", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 23, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 81.0000032991976, + "st": 0, + "bm": 0 + } + ], + "markers": [] +} \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt index df88ca9..90bc11b 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/AgendaDayFragment.kt @@ -23,6 +23,8 @@ import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearSmoothScroller import androidx.recyclerview.widget.RecyclerView +import com.airbnb.lottie.LottieAnimationView +import com.airbnb.lottie.LottieDrawable import com.google.android.material.button.MaterialButton import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.data.Schedule.ScheduleRow @@ -48,6 +50,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { private lateinit var emptyFilterView: View private lateinit var scrollToCurrentButton: MaterialButton private lateinit var viewModel: AgendaDayViewModel + private lateinit var agendaProgressView: LottieAnimationView private val viewModelFactory = object : ViewModelProvider.Factory { override fun create(modelClass: Class): T { @@ -130,6 +133,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { emptyStateView = view.findViewById(R.id.empty_view) emptyFilterView = view.findViewById(R.id.empty_filter_view) scrollToCurrentButton = view.findViewById(R.id.scroll_to_current_session) + agendaProgressView = view.findViewById(R.id.speaker_image) layoutManager = LinearLayoutManager(requireActivity().applicationContext) agendaRecyler.layoutManager = layoutManager @@ -149,6 +153,13 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { activity?.supportFragmentManager?.addOnBackStackChangedListener(backStackChangeListener) } + override fun onStart() { + super.onStart() + agendaProgressView.setAnimation("dancing_droid.json") + agendaProgressView.playAnimation() + agendaProgressView.repeatCount = LottieDrawable.INFINITE + } + private val backStackChangeListener: () -> Unit = { if (viewModel.onlyMyAgenda) { fetchScheduleData() @@ -286,6 +297,7 @@ class AgendaDayFragment : Fragment(), FlexibleAdapter.OnItemClickListener { agendaRecyler.addOnChildAttachStateChangeListener(currentSessionVisibleListener) headerAdapter!!.addListener(this) agendaRecyler.adapter = headerAdapter + agendaProgressView.visibility = View.GONE agendaRecyler .addItemDecoration(FlexibleItemDecoration(agendaRecyler.context) .withDefaultDivider()) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt index 251c0df..5030288 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/agenda/ScheduleAdapterItem.kt @@ -1,6 +1,5 @@ package com.mentalmachines.droidcon_boston.views.agenda -import android.graphics.Bitmap import android.util.TypedValue import android.view.View import android.widget.ImageView @@ -8,11 +7,6 @@ import android.widget.TextView import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide -import com.bumptech.glide.load.resource.drawable.GlideDrawable -import com.bumptech.glide.request.RequestListener -import com.bumptech.glide.request.animation.GlideAnimation -import com.bumptech.glide.request.target.SimpleTarget -import com.bumptech.glide.request.target.Target import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.data.Schedule import com.mentalmachines.droidcon_boston.data.UserAgendaRepo @@ -22,7 +16,6 @@ import eu.davidea.flexibleadapter.items.AbstractSectionableItem import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.viewholders.FlexibleViewHolder import timber.log.Timber -import java.lang.Exception import java.text.ParseException import java.text.SimpleDateFormat import java.util.* @@ -33,10 +26,10 @@ const val CURRENT_ITEM_MARKER_TAG = "CURRENT_ITEM_MARKER_TAG" * Used for displaying the schedule with sticky headers with optional day filtering */ class ScheduleAdapterItem internal constructor( - val itemData: Schedule.ScheduleRow, - header: ScheduleAdapterItemHeader + val itemData: Schedule.ScheduleRow, + header: ScheduleAdapterItemHeader ) : - AbstractSectionableItem(header) { + AbstractSectionableItem(header) { private var startTime: Date = Date() @@ -73,17 +66,17 @@ class ScheduleAdapterItem internal constructor( } override fun createViewHolder( - view: View, - adapter: FlexibleAdapter> + view: View, + adapter: FlexibleAdapter> ): ViewHolder { return ScheduleAdapterItem.ViewHolder(view, adapter) } override fun bindViewHolder( - adapter: FlexibleAdapter>?, - holder: ViewHolder, - position: Int, - payloads: MutableList + adapter: FlexibleAdapter>?, + holder: ViewHolder, + position: Int, + payloads: MutableList ) { val userAgendaRepo = UserAgendaRepo.getInstance(holder.bookmarkIndicator.context) @@ -123,15 +116,9 @@ class ScheduleAdapterItem internal constructor( val context = holder.title.context - Glide.with(context).load(itemData.photoUrlMap[itemData.primarySpeakerName]) - .asBitmap() - .transform(CircleTransform(context)) - .into(object : SimpleTarget() { - override fun onResourceReady(resource: Bitmap?, glideAnimation: GlideAnimation?) { - holder.avatar.setImageBitmap(resource) - } - }) + .transform(CircleTransform(context)).placeholder(R.drawable.emo_im_cool).crossFade() + .into(holder.avatar) holder.bookmarkIndicator.visibility = if (userAgendaRepo.isSessionBookmarked(itemData.id)) View.VISIBLE @@ -142,10 +129,10 @@ class ScheduleAdapterItem internal constructor( val availableColor = if (itemData.isOver) R.color.colorGray else R.color.colorAccent holder.availableIndicator.setBackgroundColor( - ContextCompat.getColor( - holder.availableIndicator.context, - availableColor - ) + ContextCompat.getColor( + holder.availableIndicator.context, + availableColor + ) ) if (itemData.isCurrentSession) { @@ -195,9 +182,9 @@ class ScheduleAdapterItem internal constructor( } constructor(view: View, adapter: FlexibleAdapter<*>, stickyHeader: Boolean) : super( - view, - adapter, - stickyHeader + view, + adapter, + stickyHeader ) { findViews(view) diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt index 9dcdcda..1004582 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt @@ -1,10 +1,8 @@ package com.mentalmachines.droidcon_boston.views.detail import android.content.res.ColorStateList -import android.graphics.Bitmap import android.os.Bundle import android.text.method.LinkMovementMethod -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -17,11 +15,7 @@ import androidx.lifecycle.Observer import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders -import com.airbnb.lottie.LottieAnimationView -import com.airbnb.lottie.LottieDrawable import com.bumptech.glide.Glide -import com.bumptech.glide.request.animation.GlideAnimation -import com.bumptech.glide.request.target.SimpleTarget import com.google.android.material.snackbar.Snackbar import com.mentalmachines.droidcon_boston.R import com.mentalmachines.droidcon_boston.R.string @@ -36,7 +30,6 @@ import com.mentalmachines.droidcon_boston.utils.getHtmlFormattedSpanned import com.mentalmachines.droidcon_boston.views.MainActivity import com.mentalmachines.droidcon_boston.views.transform.CircleTransform import kotlinx.android.synthetic.main.agenda_detail_fragment.* -import timber.log.Timber class AgendaDetailFragment : Fragment() { @@ -115,6 +108,8 @@ class AgendaDetailFragment : Fragment() { showBookmarkStatus() } + + populateSpeakersInformation() } override fun onDestroyView() { @@ -157,7 +152,7 @@ class AgendaDetailFragment : Fragment() { } // Add an imageview to the relative layout - val tempImg = LottieAnimationView(activity) + val tempImg = ImageView(activity) val lp = RelativeLayout.LayoutParams(imgViewSize, imgViewSize) if (speakerName == viewModel.speakerNames.first()) { lp.setMargins(marginValue, 0, 0, defaultLeftMargin) @@ -173,18 +168,12 @@ class AgendaDetailFragment : Fragment() { // add speakerName as a child to the relative layout agendaDetailView.addView(tempImg) - tempImg.setAnimation("dancing_droid.json") - tempImg.playAnimation() - tempImg.repeatCount = LottieDrawable.INFINITE - Glide.with(activity) + Glide.with(this) .load(viewModel.getPhotoForSpeaker(speakerName)) - .asBitmap() .transform(CircleTransform(tempImg.context)) - .into(object : SimpleTarget(){ - override fun onResourceReady(resource: Bitmap?, glideAnimation: GlideAnimation?) { - tempImg.setImageBitmap(resource) - } - }) + .placeholder(R.drawable.emo_im_cool) + .crossFade() + .into(tempImg) tempImg.setOnClickListener { val eventSpeaker = viewModel.getSpeaker(speakerName) @@ -243,8 +232,7 @@ class AgendaDetailFragment : Fragment() { agendaDetailFragment.arguments = arguments supportFragmentManager.beginTransaction() - .replace(R.id.fragment_container, agendaDetailFragment) - .addToBackStack(null).commit() + .add(R.id.fragment_container, agendaDetailFragment).addToBackStack(null).commit() } } } diff --git a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml index d31ffa0..9b2b8a3 100644 --- a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml @@ -30,4 +30,15 @@ + + diff --git a/Droidcon-Boston/app/src/main/res/layout/schedule_item.xml b/Droidcon-Boston/app/src/main/res/layout/schedule_item.xml index 3245580..5b3b245 100644 --- a/Droidcon-Boston/app/src/main/res/layout/schedule_item.xml +++ b/Droidcon-Boston/app/src/main/res/layout/schedule_item.xml @@ -113,15 +113,12 @@ android:layout_height="90dp" android:layout_gravity="center_vertical"> - Date: Sun, 10 Mar 2019 00:05:41 +0530 Subject: [PATCH 095/173] feat: added the dimens to progress in agenda fragment --- .../app/src/main/res/layout/agenda_day_fragment.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml index 9b2b8a3..f729e59 100644 --- a/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml +++ b/Droidcon-Boston/app/src/main/res/layout/agenda_day_fragment.xml @@ -32,8 +32,8 @@ Date: Sat, 9 Mar 2019 14:12:11 -0500 Subject: [PATCH 096/173] handle no room event instead of crashing --- Droidcon-Boston/app/build.gradle | 18 ++++++++++++------ .../droidcon_boston/data/FirebaseDatabase.kt | 2 +- .../droidcon_boston/data/Schedule.kt | 2 +- .../views/detail/AgendaDetailViewModel.kt | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Droidcon-Boston/app/build.gradle b/Droidcon-Boston/app/build.gradle index 7a4cf46..14eb480 100644 --- a/Droidcon-Boston/app/build.gradle +++ b/Droidcon-Boston/app/build.gradle @@ -24,12 +24,18 @@ android { useSupportLibrary = true } - buildConfigField "int", "EVENT_YEAR", "2018" - buildConfigField "int", "EVENT_MONTH", "03" - buildConfigField "int", "EVENT_DAY_ONE", "26" - buildConfigField "int", "EVENT_DAY_TWO", "27" - buildConfigField "String", "EVENT_DAY_ONE_STRING", "\"03/26/2018\"" - buildConfigField "String", "EVENT_DAY_TWO_STRING", "\"03/27/2018\"" + javaCompileOptions { + annotationProcessorOptions { + includeCompileClasspath true + } + } + + buildConfigField "int", "EVENT_YEAR", "2019" + buildConfigField "int", "EVENT_MONTH", "04" + buildConfigField "int", "EVENT_DAY_ONE", "8" + buildConfigField "int", "EVENT_DAY_TWO", "9" + buildConfigField "String", "EVENT_DAY_ONE_STRING", "\"04/08/2019\"" + buildConfigField "String", "EVENT_DAY_TWO_STRING", "\"04/09/2019\"" } signingConfigs { diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt index 142af0c..42d0eca 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/FirebaseDatabase.kt @@ -78,7 +78,7 @@ open class FirebaseDatabase { } row.id = scheduleId - row.room = roomNames.keys.first() + row.room = roomNames.keys.firstOrNull() row.trackSortOrder = trackSortOrder row.primarySpeakerName = primarySpeakerName row.speakerNames = speakerNames.keys.toList() diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt index ada5036..cca228b 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/data/Schedule.kt @@ -22,7 +22,7 @@ class Schedule { var speakerNameToOrgName: HashMap = HashMap(0), var utcStartTimeString: String = "", var endTime: String = "", - var room: String = "", + var room: String? = null, var date: String = "", var trackSortOrder: Int = 0, var photoUrlMap: HashMap = HashMap(0), diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailViewModel.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailViewModel.kt index 3378e00..8a620a5 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailViewModel.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailViewModel.kt @@ -45,7 +45,7 @@ class AgendaDetailViewModel( val talkTitle: String get() = scheduleRowItem.talkTitle - val room: String + val room: String? get() = scheduleRowItem.room val startTime: String From 5945095084a12155330fd8f9b58f36e82ef161c2 Mon Sep 17 00:00:00 2001 From: adammc331 Date: Sat, 9 Mar 2019 01:28:58 -0500 Subject: [PATCH 097/173] Added rating dialog to detail fragment for #118. Not hooked up to any API or handling the rating yet. --- .../views/detail/AgendaDetailFragment.kt | 23 +++++++ .../views/rating/RatingDialog.kt | 58 ++++++++++++++++++ .../app/src/main/res/layout/dialog_rating.xml | 61 +++++++++++++++++++ .../src/main/res/menu/menu_agenda_detail.xml | 8 +++ .../app/src/main/res/values/strings.xml | 4 ++ 5 files changed, 154 insertions(+) create mode 100644 Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/rating/RatingDialog.kt create mode 100644 Droidcon-Boston/app/src/main/res/layout/dialog_rating.xml create mode 100644 Droidcon-Boston/app/src/main/res/menu/menu_agenda_detail.xml diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt index 496c460..f1e63a2 100644 --- a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/detail/AgendaDetailFragment.kt @@ -4,6 +4,9 @@ import android.content.res.ColorStateList import android.os.Bundle import android.text.method.LinkMovementMethod 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 android.widget.ImageView @@ -28,6 +31,7 @@ import com.mentalmachines.droidcon_boston.utils.NotificationUtils import com.mentalmachines.droidcon_boston.utils.ServiceLocator.Companion.gson import com.mentalmachines.droidcon_boston.utils.getHtmlFormattedSpanned import com.mentalmachines.droidcon_boston.views.MainActivity +import com.mentalmachines.droidcon_boston.views.rating.RatingDialog import com.mentalmachines.droidcon_boston.views.transform.CircleTransform import kotlinx.android.synthetic.main.agenda_detail_fragment.* @@ -49,6 +53,11 @@ class AgendaDetailFragment : Fragment() { private lateinit var viewModel: AgendaDetailViewModel + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setHasOptionsMenu(true) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -217,6 +226,20 @@ class AgendaDetailFragment : Fragment() { fab_agenda_detail_bookmark.backgroundTintList = ColorStateList.valueOf(color) } + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + inflater?.inflate(R.menu.menu_agenda_detail, menu) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + return when (item?.itemId) { + R.id.rate -> { + RatingDialog().show(fragmentManager, "RATE_DIALOG") + true + } + else -> super.onOptionsItemSelected(item) + } + } + companion object { fun addDetailFragmentToStack( supportFragmentManager: FragmentManager, diff --git a/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/rating/RatingDialog.kt b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/rating/RatingDialog.kt new file mode 100644 index 0000000..b9ed247 --- /dev/null +++ b/Droidcon-Boston/app/src/main/java/com/mentalmachines/droidcon_boston/views/rating/RatingDialog.kt @@ -0,0 +1,58 @@ +package com.mentalmachines.droidcon_boston.views.rating + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.RatingBar +import androidx.fragment.app.DialogFragment +import com.google.android.material.textfield.TextInputEditText +import com.mentalmachines.droidcon_boston.R + +class RatingDialog : DialogFragment() { + private var talkRatingBar: RatingBar? = null + private var talkFeedbackInput: TextInputEditText? = null + private var cancelButton: Button? = null + private var submitButton: Button? = null + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = inflater.inflate(R.layout.dialog_rating, container, false) + + findViews(view) + + setupClickListeners() + + return view + } + + private fun findViews(view: View) { + talkRatingBar = view.findViewById(R.id.talk_rating) + talkFeedbackInput = view.findViewById(R.id.talk_feedback) + cancelButton = view.findViewById(R.id.cancel) + submitButton = view.findViewById(R.id.submit) + } + + private fun setupClickListeners() { + cancelButton?.setOnClickListener { + this.dismiss() + } + + submitButton?.setOnClickListener { + //TODO: Handle submission + this.dismiss() + } + } + + override fun onStart() { + super.onStart() + + val width = ViewGroup.LayoutParams.MATCH_PARENT + val height = ViewGroup.LayoutParams.WRAP_CONTENT + dialog?.window?.setLayout(width, height) + } +} \ No newline at end of file diff --git a/Droidcon-Boston/app/src/main/res/layout/dialog_rating.xml b/Droidcon-Boston/app/src/main/res/layout/dialog_rating.xml new file mode 100644 index 0000000..06d3ef7 --- /dev/null +++ b/Droidcon-Boston/app/src/main/res/layout/dialog_rating.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + +