Loading app/build.gradle +4 −2 Original line number Diff line number Diff line Loading @@ -9,7 +9,6 @@ apply plugin: 'com.android.application' apply plugin: 'com.mikepenz.aboutlibraries.plugin' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' apply plugin: 'org.jetbrains.dokka' Loading Loading @@ -48,7 +47,10 @@ android { jvmTarget = "1.8" } buildFeatures.dataBinding = true buildFeatures { viewBinding = true dataBinding = true } flavorDimensions "distribution" productFlavors { Loading app/src/main/java/at/bitfire/davdroid/ui/AboutActivity.kt +53 −27 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ package at.bitfire.davdroid.ui import android.app.Application import android.content.Context import android.os.Build import android.os.Bundle import android.text.Spanned Loading @@ -17,7 +18,6 @@ import android.util.DisplayMetrics import android.view.* import androidx.annotation.UiThread import androidx.appcompat.app.AppCompatActivity import androidx.cardview.widget.CardView import androidx.core.text.HtmlCompat import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager Loading @@ -32,12 +32,12 @@ import androidx.recyclerview.widget.RecyclerView import at.bitfire.davdroid.App import at.bitfire.davdroid.BuildConfig import at.bitfire.davdroid.R import at.bitfire.davdroid.databinding.AboutBinding import at.bitfire.davdroid.databinding.AboutLanguagesBinding import at.bitfire.davdroid.databinding.AboutTranslationBinding import at.bitfire.davdroid.databinding.ActivityAboutBinding import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.LibsBuilder import kotlinx.android.synthetic.main.about.* import kotlinx.android.synthetic.main.about_languages.* import kotlinx.android.synthetic.main.about_translation.view.* import kotlinx.android.synthetic.main.activity_about.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.apache.commons.io.IOUtils Loading @@ -57,15 +57,20 @@ class AboutActivity: AppCompatActivity() { } private lateinit var binding: ActivityAboutBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_about) setSupportActionBar(toolbar) binding = ActivityAboutBinding.inflate(layoutInflater) setContentView(binding.root) setSupportActionBar(binding.toolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) viewpager.adapter = TabsAdapter(supportFragmentManager) tabs.setupWithViewPager(viewpager, false) binding.viewpager.adapter = TabsAdapter(supportFragmentManager) binding.tabs.setupWithViewPager(binding.viewpager, false) } override fun onCreateOptionsMenu(menu: Menu?): Boolean { Loading Loading @@ -115,67 +120,88 @@ class AboutActivity: AppCompatActivity() { class AppFragment: Fragment() { private var _binding: AboutBinding? = null private val binding get() = _binding!! val model by viewModels<TextFileModel>() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = inflater.inflate(R.layout.about, container, false)!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { _binding = AboutBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { app_name.setText(R.string.app_name) app_version.text = getString(R.string.about_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE) build_time.text = getString(R.string.about_build_date, SimpleDateFormat.getDateInstance().format(BuildConfig.buildTime)) binding.appName.setText(R.string.app_name) binding.appVersion.text = getString(R.string.about_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE) binding.buildTime.text = getString(R.string.about_build_date, SimpleDateFormat.getDateInstance().format(BuildConfig.buildTime)) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) icon.setImageDrawable(resources.getDrawableForDensity(R.mipmap.ic_launcher, DisplayMetrics.DENSITY_XXXHIGH, null)) binding.icon.setImageDrawable(resources.getDrawableForDensity(R.mipmap.ic_launcher, DisplayMetrics.DENSITY_XXXHIGH, null)) pixels.text = HtmlCompat.fromHtml(pixelsHtml, HtmlCompat.FROM_HTML_MODE_LEGACY) binding.pixels.text = HtmlCompat.fromHtml(pixelsHtml, HtmlCompat.FROM_HTML_MODE_LEGACY) if (true /* open-source version */) { warranty.setText(R.string.about_license_info_no_warranty) binding.warranty.setText(R.string.about_license_info_no_warranty) model.initialize("gplv3.html", true) model.htmlText.observe(viewLifecycleOwner, { spanned -> license_text.text = spanned binding.licenseText.text = spanned }) } } override fun onDestroyView() { super.onDestroyView() _binding = null } } class LanguagesFragment: Fragment() { private var _binding: AboutLanguagesBinding? = null private val binding get() = _binding!! val model by viewModels<TranslationsModel>() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = inflater.inflate(R.layout.about_languages, container, false)!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = AboutLanguagesBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { model.initialize("translators.json", false) model.translations.observe(viewLifecycleOwner, { translations -> translators.adapter = TranslationsAdapter(translations) binding.translators.adapter = TranslationsAdapter(translations) }) translators.layoutManager = LinearLayoutManager(requireActivity()) binding.translators.layoutManager = LinearLayoutManager(requireActivity()) } override fun onDestroyView() { super.onDestroyView() _binding = null } class TranslationsAdapter( val translations: List<TranslationsModel.Translation> ): RecyclerView.Adapter<TranslationsAdapter.ViewHolder>() { class ViewHolder(val cardView: CardView): RecyclerView.ViewHolder(cardView) private lateinit var binding: AboutTranslationBinding class ViewHolder(val context: Context, val binding: AboutTranslationBinding): RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val tv = LayoutInflater.from(parent.context).inflate(R.layout.about_translation, parent, false) as CardView return ViewHolder(tv) binding = AboutTranslationBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ViewHolder(parent.context, binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val translation = translations[position] holder.cardView.apply { holder.binding.apply { language.text = translation.language val profiles = translation.translators.map { "<a href='https://www.transifex.com/user/profile/$it'>$it</a>" } translators.text = HtmlCompat.fromHtml( context.getString(R.string.about_translations_thanks, profiles.joinToString(", ")), holder.context.getString(R.string.about_translations_thanks, profiles.joinToString(", ")), HtmlCompat.FROM_HTML_MODE_COMPACT) translators.movementMethod = LinkMovementMethod.getInstance() } Loading app/src/main/java/at/bitfire/davdroid/ui/AccountListFragment.kt +27 −18 Original line number Diff line number Diff line Loading @@ -33,39 +33,43 @@ import androidx.recyclerview.widget.RecyclerView import at.bitfire.davdroid.DavUtils import at.bitfire.davdroid.DavUtils.SyncStatus import at.bitfire.davdroid.R import at.bitfire.davdroid.databinding.AccountListBinding import at.bitfire.davdroid.databinding.AccountListItemBinding import at.bitfire.davdroid.ui.account.AccountActivity import kotlinx.android.synthetic.main.account_list.* import kotlinx.android.synthetic.main.account_list_item.view.* import java.text.Collator class AccountListFragment: Fragment() { private var _binding: AccountListBinding? = null private val binding get() = _binding!! val model by viewModels<Model>() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { setHasOptionsMenu(true) return inflater.inflate(R.layout.account_list, container, false) _binding = AccountListBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) model.networkAvailable.observe(viewLifecycleOwner, { networkAvailable -> no_network_info.visibility = if (networkAvailable) View.GONE else View.VISIBLE binding.noNetworkInfo.visibility = if (networkAvailable) View.GONE else View.VISIBLE }) val accountAdapter = AccountAdapter(requireActivity()) list.apply { binding.list.apply { layoutManager = LinearLayoutManager(requireActivity()) adapter = accountAdapter } model.accounts.observe(viewLifecycleOwner, { accounts -> if (accounts.isEmpty()) { list.visibility = View.GONE empty.visibility = View.VISIBLE binding.list.visibility = View.GONE binding.empty.visibility = View.VISIBLE } else { list.visibility = View.VISIBLE empty.visibility = View.GONE binding.list.visibility = View.VISIBLE binding.empty.visibility = View.GONE } accountAdapter.submitList(accounts) requireActivity().invalidateOptionsMenu() Loading @@ -82,6 +86,11 @@ class AccountListFragment: Fragment() { } } override fun onDestroyView() { super.onDestroyView() _binding = null } class AccountAdapter( val activity: Activity Loading @@ -93,18 +102,18 @@ class AccountListFragment: Fragment() { oldItem == newItem } ) { class ViewHolder(val v: View): RecyclerView.ViewHolder(v) class ViewHolder(val binding: AccountListItemBinding): RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val v = LayoutInflater.from(parent.context).inflate(R.layout.account_list_item, parent, false) return ViewHolder(v) val binding = AccountListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ViewHolder(binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val v = holder.v val accountInfo = currentList[position] v.setOnClickListener { holder.binding.root.setOnClickListener { val intent = Intent(activity, AccountActivity::class.java) intent.putExtra(AccountActivity.EXTRA_ACCOUNT, accountInfo.account) activity.startActivity(intent) Loading @@ -112,23 +121,23 @@ class AccountListFragment: Fragment() { when (accountInfo.status) { SyncStatus.ACTIVE -> { v.progress.apply { holder.binding.progress.apply { alpha = 1.0f isIndeterminate = true visibility = View.VISIBLE } } SyncStatus.PENDING -> { v.progress.apply { holder.binding.progress.apply { alpha = 0.4f isIndeterminate = false progress = 100 visibility = View.VISIBLE } } else -> v.progress.visibility = View.INVISIBLE else -> holder.binding.progress.visibility = View.INVISIBLE } v.account_name.text = accountInfo.account.name holder.binding.accountName.text = accountInfo.account.name } } Loading app/src/main/java/at/bitfire/davdroid/ui/AccountsActivity.kt +17 −15 Original line number Diff line number Diff line Loading @@ -23,13 +23,11 @@ import androidx.core.content.getSystemService import androidx.core.view.GravityCompat import at.bitfire.davdroid.DavUtils import at.bitfire.davdroid.R import at.bitfire.davdroid.databinding.ActivityAccountsBinding import at.bitfire.davdroid.ui.intro.IntroActivity import at.bitfire.davdroid.ui.setup.LoginActivity import com.google.android.material.navigation.NavigationView import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.accounts_content.* import kotlinx.android.synthetic.main.activity_accounts.* import kotlinx.android.synthetic.main.activity_accounts.view.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch Loading @@ -43,6 +41,8 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele const val REQUEST_INTRO = 0 } private lateinit var binding: ActivityAccountsBinding private var syncStatusSnackbar: Snackbar? = null private var syncStatusObserver: Any? = null Loading @@ -60,21 +60,23 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele } } setContentView(R.layout.activity_accounts) setSupportActionBar(toolbar) binding = ActivityAccountsBinding.inflate(layoutInflater) setContentView(binding.root) fab.setOnClickListener { val content = binding.content setSupportActionBar(binding.content.toolbar) content.fab.setOnClickListener { startActivity(Intent(this, LoginActivity::class.java)) } fab.show() content.fab.show() val toggle = ActionBarDrawerToggle( this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) drawer_layout.addDrawerListener(toggle) this, binding.drawerLayout, binding.content.toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) binding.drawerLayout.addDrawerListener(toggle) toggle.syncState() nav_view.setNavigationItemSelectedListener(this) nav_view.itemIconTintList = null binding.navView.setNavigationItemSelectedListener(this) binding.navView.itemIconTintList = null // handle "Sync all" intent from launcher shortcut if (savedInstanceState == null && intent.action == Intent.ACTION_SYNC) Loading @@ -84,7 +86,7 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele override fun onResume() { super.onResume() accountsDrawerHandler.initMenu(this, drawer_layout.nav_view.menu) accountsDrawerHandler.initMenu(this, binding.navView.menu) onStatusChanged(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS) syncStatusObserver = ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, this) Loading Loading @@ -125,15 +127,15 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele } override fun onBackPressed() { if (drawer_layout.isDrawerOpen(GravityCompat.START)) drawer_layout.closeDrawer(GravityCompat.START) if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) binding.drawerLayout.closeDrawer(GravityCompat.START) else super.onBackPressed() } override fun onNavigationItemSelected(item: MenuItem): Boolean { val processed = accountsDrawerHandler.onNavigationItemSelected(this, item) drawer_layout.closeDrawer(GravityCompat.START) binding.drawerLayout.closeDrawer(GravityCompat.START) return processed } Loading app/src/main/java/at/bitfire/davdroid/ui/TasksFragment.kt +9 −4 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData import androidx.lifecycle.observe import at.bitfire.davdroid.PackageChangedReceiver import at.bitfire.davdroid.R import at.bitfire.davdroid.databinding.ActivityTasksBinding Loading @@ -23,15 +22,16 @@ import at.bitfire.davdroid.resource.TaskUtils import at.bitfire.davdroid.settings.SettingsManager import at.bitfire.ical4android.TaskProvider.ProviderName import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.activity_tasks.* class TasksFragment: Fragment() { private var _binding: ActivityTasksBinding? = null private val binding get() = _binding!! val model by viewModels<Model>() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { val binding = ActivityTasksBinding.inflate(inflater, container, false) _binding = ActivityTasksBinding.inflate(inflater, container, false) binding.lifecycleOwner = viewLifecycleOwner binding.model = model Loading Loading @@ -63,13 +63,18 @@ class TasksFragment: Fragment() { return binding.root } override fun onDestroyView() { super.onDestroyView() _binding = null } private fun installApp(packageName: String) { val uri = Uri.parse("market://details?id=$packageName") val intent = Intent(Intent.ACTION_VIEW, uri) if (intent.resolveActivity(requireActivity().packageManager) != null) startActivity(intent) else Snackbar.make(frame, R.string.intro_tasks_no_app_store, Snackbar.LENGTH_LONG).show() Snackbar.make(binding.frame, R.string.intro_tasks_no_app_store, Snackbar.LENGTH_LONG).show() } Loading Loading
app/build.gradle +4 −2 Original line number Diff line number Diff line Loading @@ -9,7 +9,6 @@ apply plugin: 'com.android.application' apply plugin: 'com.mikepenz.aboutlibraries.plugin' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' apply plugin: 'org.jetbrains.dokka' Loading Loading @@ -48,7 +47,10 @@ android { jvmTarget = "1.8" } buildFeatures.dataBinding = true buildFeatures { viewBinding = true dataBinding = true } flavorDimensions "distribution" productFlavors { Loading
app/src/main/java/at/bitfire/davdroid/ui/AboutActivity.kt +53 −27 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ package at.bitfire.davdroid.ui import android.app.Application import android.content.Context import android.os.Build import android.os.Bundle import android.text.Spanned Loading @@ -17,7 +18,6 @@ import android.util.DisplayMetrics import android.view.* import androidx.annotation.UiThread import androidx.appcompat.app.AppCompatActivity import androidx.cardview.widget.CardView import androidx.core.text.HtmlCompat import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager Loading @@ -32,12 +32,12 @@ import androidx.recyclerview.widget.RecyclerView import at.bitfire.davdroid.App import at.bitfire.davdroid.BuildConfig import at.bitfire.davdroid.R import at.bitfire.davdroid.databinding.AboutBinding import at.bitfire.davdroid.databinding.AboutLanguagesBinding import at.bitfire.davdroid.databinding.AboutTranslationBinding import at.bitfire.davdroid.databinding.ActivityAboutBinding import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.LibsBuilder import kotlinx.android.synthetic.main.about.* import kotlinx.android.synthetic.main.about_languages.* import kotlinx.android.synthetic.main.about_translation.view.* import kotlinx.android.synthetic.main.activity_about.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.apache.commons.io.IOUtils Loading @@ -57,15 +57,20 @@ class AboutActivity: AppCompatActivity() { } private lateinit var binding: ActivityAboutBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_about) setSupportActionBar(toolbar) binding = ActivityAboutBinding.inflate(layoutInflater) setContentView(binding.root) setSupportActionBar(binding.toolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) viewpager.adapter = TabsAdapter(supportFragmentManager) tabs.setupWithViewPager(viewpager, false) binding.viewpager.adapter = TabsAdapter(supportFragmentManager) binding.tabs.setupWithViewPager(binding.viewpager, false) } override fun onCreateOptionsMenu(menu: Menu?): Boolean { Loading Loading @@ -115,67 +120,88 @@ class AboutActivity: AppCompatActivity() { class AppFragment: Fragment() { private var _binding: AboutBinding? = null private val binding get() = _binding!! val model by viewModels<TextFileModel>() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = inflater.inflate(R.layout.about, container, false)!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { _binding = AboutBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { app_name.setText(R.string.app_name) app_version.text = getString(R.string.about_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE) build_time.text = getString(R.string.about_build_date, SimpleDateFormat.getDateInstance().format(BuildConfig.buildTime)) binding.appName.setText(R.string.app_name) binding.appVersion.text = getString(R.string.about_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE) binding.buildTime.text = getString(R.string.about_build_date, SimpleDateFormat.getDateInstance().format(BuildConfig.buildTime)) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) icon.setImageDrawable(resources.getDrawableForDensity(R.mipmap.ic_launcher, DisplayMetrics.DENSITY_XXXHIGH, null)) binding.icon.setImageDrawable(resources.getDrawableForDensity(R.mipmap.ic_launcher, DisplayMetrics.DENSITY_XXXHIGH, null)) pixels.text = HtmlCompat.fromHtml(pixelsHtml, HtmlCompat.FROM_HTML_MODE_LEGACY) binding.pixels.text = HtmlCompat.fromHtml(pixelsHtml, HtmlCompat.FROM_HTML_MODE_LEGACY) if (true /* open-source version */) { warranty.setText(R.string.about_license_info_no_warranty) binding.warranty.setText(R.string.about_license_info_no_warranty) model.initialize("gplv3.html", true) model.htmlText.observe(viewLifecycleOwner, { spanned -> license_text.text = spanned binding.licenseText.text = spanned }) } } override fun onDestroyView() { super.onDestroyView() _binding = null } } class LanguagesFragment: Fragment() { private var _binding: AboutLanguagesBinding? = null private val binding get() = _binding!! val model by viewModels<TranslationsModel>() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = inflater.inflate(R.layout.about_languages, container, false)!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = AboutLanguagesBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { model.initialize("translators.json", false) model.translations.observe(viewLifecycleOwner, { translations -> translators.adapter = TranslationsAdapter(translations) binding.translators.adapter = TranslationsAdapter(translations) }) translators.layoutManager = LinearLayoutManager(requireActivity()) binding.translators.layoutManager = LinearLayoutManager(requireActivity()) } override fun onDestroyView() { super.onDestroyView() _binding = null } class TranslationsAdapter( val translations: List<TranslationsModel.Translation> ): RecyclerView.Adapter<TranslationsAdapter.ViewHolder>() { class ViewHolder(val cardView: CardView): RecyclerView.ViewHolder(cardView) private lateinit var binding: AboutTranslationBinding class ViewHolder(val context: Context, val binding: AboutTranslationBinding): RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val tv = LayoutInflater.from(parent.context).inflate(R.layout.about_translation, parent, false) as CardView return ViewHolder(tv) binding = AboutTranslationBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ViewHolder(parent.context, binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val translation = translations[position] holder.cardView.apply { holder.binding.apply { language.text = translation.language val profiles = translation.translators.map { "<a href='https://www.transifex.com/user/profile/$it'>$it</a>" } translators.text = HtmlCompat.fromHtml( context.getString(R.string.about_translations_thanks, profiles.joinToString(", ")), holder.context.getString(R.string.about_translations_thanks, profiles.joinToString(", ")), HtmlCompat.FROM_HTML_MODE_COMPACT) translators.movementMethod = LinkMovementMethod.getInstance() } Loading
app/src/main/java/at/bitfire/davdroid/ui/AccountListFragment.kt +27 −18 Original line number Diff line number Diff line Loading @@ -33,39 +33,43 @@ import androidx.recyclerview.widget.RecyclerView import at.bitfire.davdroid.DavUtils import at.bitfire.davdroid.DavUtils.SyncStatus import at.bitfire.davdroid.R import at.bitfire.davdroid.databinding.AccountListBinding import at.bitfire.davdroid.databinding.AccountListItemBinding import at.bitfire.davdroid.ui.account.AccountActivity import kotlinx.android.synthetic.main.account_list.* import kotlinx.android.synthetic.main.account_list_item.view.* import java.text.Collator class AccountListFragment: Fragment() { private var _binding: AccountListBinding? = null private val binding get() = _binding!! val model by viewModels<Model>() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { setHasOptionsMenu(true) return inflater.inflate(R.layout.account_list, container, false) _binding = AccountListBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) model.networkAvailable.observe(viewLifecycleOwner, { networkAvailable -> no_network_info.visibility = if (networkAvailable) View.GONE else View.VISIBLE binding.noNetworkInfo.visibility = if (networkAvailable) View.GONE else View.VISIBLE }) val accountAdapter = AccountAdapter(requireActivity()) list.apply { binding.list.apply { layoutManager = LinearLayoutManager(requireActivity()) adapter = accountAdapter } model.accounts.observe(viewLifecycleOwner, { accounts -> if (accounts.isEmpty()) { list.visibility = View.GONE empty.visibility = View.VISIBLE binding.list.visibility = View.GONE binding.empty.visibility = View.VISIBLE } else { list.visibility = View.VISIBLE empty.visibility = View.GONE binding.list.visibility = View.VISIBLE binding.empty.visibility = View.GONE } accountAdapter.submitList(accounts) requireActivity().invalidateOptionsMenu() Loading @@ -82,6 +86,11 @@ class AccountListFragment: Fragment() { } } override fun onDestroyView() { super.onDestroyView() _binding = null } class AccountAdapter( val activity: Activity Loading @@ -93,18 +102,18 @@ class AccountListFragment: Fragment() { oldItem == newItem } ) { class ViewHolder(val v: View): RecyclerView.ViewHolder(v) class ViewHolder(val binding: AccountListItemBinding): RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val v = LayoutInflater.from(parent.context).inflate(R.layout.account_list_item, parent, false) return ViewHolder(v) val binding = AccountListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ViewHolder(binding) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val v = holder.v val accountInfo = currentList[position] v.setOnClickListener { holder.binding.root.setOnClickListener { val intent = Intent(activity, AccountActivity::class.java) intent.putExtra(AccountActivity.EXTRA_ACCOUNT, accountInfo.account) activity.startActivity(intent) Loading @@ -112,23 +121,23 @@ class AccountListFragment: Fragment() { when (accountInfo.status) { SyncStatus.ACTIVE -> { v.progress.apply { holder.binding.progress.apply { alpha = 1.0f isIndeterminate = true visibility = View.VISIBLE } } SyncStatus.PENDING -> { v.progress.apply { holder.binding.progress.apply { alpha = 0.4f isIndeterminate = false progress = 100 visibility = View.VISIBLE } } else -> v.progress.visibility = View.INVISIBLE else -> holder.binding.progress.visibility = View.INVISIBLE } v.account_name.text = accountInfo.account.name holder.binding.accountName.text = accountInfo.account.name } } Loading
app/src/main/java/at/bitfire/davdroid/ui/AccountsActivity.kt +17 −15 Original line number Diff line number Diff line Loading @@ -23,13 +23,11 @@ import androidx.core.content.getSystemService import androidx.core.view.GravityCompat import at.bitfire.davdroid.DavUtils import at.bitfire.davdroid.R import at.bitfire.davdroid.databinding.ActivityAccountsBinding import at.bitfire.davdroid.ui.intro.IntroActivity import at.bitfire.davdroid.ui.setup.LoginActivity import com.google.android.material.navigation.NavigationView import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.accounts_content.* import kotlinx.android.synthetic.main.activity_accounts.* import kotlinx.android.synthetic.main.activity_accounts.view.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch Loading @@ -43,6 +41,8 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele const val REQUEST_INTRO = 0 } private lateinit var binding: ActivityAccountsBinding private var syncStatusSnackbar: Snackbar? = null private var syncStatusObserver: Any? = null Loading @@ -60,21 +60,23 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele } } setContentView(R.layout.activity_accounts) setSupportActionBar(toolbar) binding = ActivityAccountsBinding.inflate(layoutInflater) setContentView(binding.root) fab.setOnClickListener { val content = binding.content setSupportActionBar(binding.content.toolbar) content.fab.setOnClickListener { startActivity(Intent(this, LoginActivity::class.java)) } fab.show() content.fab.show() val toggle = ActionBarDrawerToggle( this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) drawer_layout.addDrawerListener(toggle) this, binding.drawerLayout, binding.content.toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) binding.drawerLayout.addDrawerListener(toggle) toggle.syncState() nav_view.setNavigationItemSelectedListener(this) nav_view.itemIconTintList = null binding.navView.setNavigationItemSelectedListener(this) binding.navView.itemIconTintList = null // handle "Sync all" intent from launcher shortcut if (savedInstanceState == null && intent.action == Intent.ACTION_SYNC) Loading @@ -84,7 +86,7 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele override fun onResume() { super.onResume() accountsDrawerHandler.initMenu(this, drawer_layout.nav_view.menu) accountsDrawerHandler.initMenu(this, binding.navView.menu) onStatusChanged(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS) syncStatusObserver = ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, this) Loading Loading @@ -125,15 +127,15 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele } override fun onBackPressed() { if (drawer_layout.isDrawerOpen(GravityCompat.START)) drawer_layout.closeDrawer(GravityCompat.START) if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) binding.drawerLayout.closeDrawer(GravityCompat.START) else super.onBackPressed() } override fun onNavigationItemSelected(item: MenuItem): Boolean { val processed = accountsDrawerHandler.onNavigationItemSelected(this, item) drawer_layout.closeDrawer(GravityCompat.START) binding.drawerLayout.closeDrawer(GravityCompat.START) return processed } Loading
app/src/main/java/at/bitfire/davdroid/ui/TasksFragment.kt +9 −4 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData import androidx.lifecycle.observe import at.bitfire.davdroid.PackageChangedReceiver import at.bitfire.davdroid.R import at.bitfire.davdroid.databinding.ActivityTasksBinding Loading @@ -23,15 +22,16 @@ import at.bitfire.davdroid.resource.TaskUtils import at.bitfire.davdroid.settings.SettingsManager import at.bitfire.ical4android.TaskProvider.ProviderName import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.activity_tasks.* class TasksFragment: Fragment() { private var _binding: ActivityTasksBinding? = null private val binding get() = _binding!! val model by viewModels<Model>() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { val binding = ActivityTasksBinding.inflate(inflater, container, false) _binding = ActivityTasksBinding.inflate(inflater, container, false) binding.lifecycleOwner = viewLifecycleOwner binding.model = model Loading Loading @@ -63,13 +63,18 @@ class TasksFragment: Fragment() { return binding.root } override fun onDestroyView() { super.onDestroyView() _binding = null } private fun installApp(packageName: String) { val uri = Uri.parse("market://details?id=$packageName") val intent = Intent(Intent.ACTION_VIEW, uri) if (intent.resolveActivity(requireActivity().packageManager) != null) startActivity(intent) else Snackbar.make(frame, R.string.intro_tasks_no_app_store, Snackbar.LENGTH_LONG).show() Snackbar.make(binding.frame, R.string.intro_tasks_no_app_store, Snackbar.LENGTH_LONG).show() } Loading