| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Copyright 2016 Christian Basler | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package ch.dissem.apps.abit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import android.content.Intent | 
					
						
							|  |  |  | import android.graphics.Point | 
					
						
							|  |  |  | import android.os.Bundle | 
					
						
							|  |  |  | import android.support.v4.app.Fragment | 
					
						
							|  |  |  | import android.support.v7.app.AppCompatActivity | 
					
						
							|  |  |  | import android.support.v7.widget.Toolbar | 
					
						
							|  |  |  | import android.view.View | 
					
						
							|  |  |  | import android.view.ViewGroup | 
					
						
							|  |  |  | import android.widget.RelativeLayout | 
					
						
							|  |  |  | import ch.dissem.apps.abit.drawer.ProfileImageListener | 
					
						
							|  |  |  | import ch.dissem.apps.abit.drawer.ProfileSelectionListener | 
					
						
							|  |  |  | import ch.dissem.apps.abit.listener.ListSelectionListener | 
					
						
							| 
									
										
										
										
											2017-11-27 22:06:25 +01:00
										 |  |  | import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARCHIVE | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | import ch.dissem.apps.abit.service.Singleton | 
					
						
							| 
									
										
										
										
											2018-01-13 21:59:20 +01:00
										 |  |  | import ch.dissem.apps.abit.service.Singleton.currentLabel | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | import ch.dissem.apps.abit.synchronization.SyncAdapter | 
					
						
							|  |  |  | import ch.dissem.apps.abit.util.Labels | 
					
						
							|  |  |  | import ch.dissem.apps.abit.util.NetworkUtils | 
					
						
							|  |  |  | import ch.dissem.apps.abit.util.Preferences | 
					
						
							|  |  |  | import ch.dissem.bitmessage.BitmessageContext | 
					
						
							|  |  |  | import ch.dissem.bitmessage.entity.BitmessageAddress | 
					
						
							|  |  |  | import ch.dissem.bitmessage.entity.Plaintext | 
					
						
							|  |  |  | import ch.dissem.bitmessage.entity.valueobject.Label | 
					
						
							|  |  |  | import com.github.amlcurran.showcaseview.ShowcaseView | 
					
						
							|  |  |  | import com.mikepenz.community_material_typeface_library.CommunityMaterial | 
					
						
							|  |  |  | import com.mikepenz.google_material_typeface_library.GoogleMaterial | 
					
						
							|  |  |  | import com.mikepenz.iconics.IconicsDrawable | 
					
						
							|  |  |  | import com.mikepenz.materialdrawer.AccountHeader | 
					
						
							|  |  |  | import com.mikepenz.materialdrawer.AccountHeaderBuilder | 
					
						
							|  |  |  | import com.mikepenz.materialdrawer.Drawer | 
					
						
							|  |  |  | import com.mikepenz.materialdrawer.DrawerBuilder | 
					
						
							|  |  |  | import com.mikepenz.materialdrawer.model.* | 
					
						
							|  |  |  | import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem | 
					
						
							|  |  |  | import com.mikepenz.materialdrawer.model.interfaces.IProfile | 
					
						
							|  |  |  | import com.mikepenz.materialdrawer.model.interfaces.Nameable | 
					
						
							|  |  |  | import io.github.kobakei.materialfabspeeddial.FabSpeedDial | 
					
						
							|  |  |  | import kotlinx.android.synthetic.main.activity_main.* | 
					
						
							|  |  |  | import org.jetbrains.anko.doAsync | 
					
						
							|  |  |  | import org.jetbrains.anko.uiThread | 
					
						
							|  |  |  | import java.io.Serializable | 
					
						
							|  |  |  | import java.lang.ref.WeakReference | 
					
						
							|  |  |  | import java.util.* | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * An activity representing a list of Messages. This activity | 
					
						
							|  |  |  |  * has different presentations for handset and tablet-size devices. On | 
					
						
							|  |  |  |  * handsets, the activity presents a list of items, which when touched, | 
					
						
							|  |  |  |  * lead to a [MessageDetailActivity] representing | 
					
						
							|  |  |  |  * item details. On tablets, the activity presents the list of items and | 
					
						
							|  |  |  |  * item details side-by-side using two vertical panes. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The activity makes heavy use of fragments. The list of items is a | 
					
						
							|  |  |  |  * [MessageListFragment] and the item details | 
					
						
							|  |  |  |  * (if present) is a [MessageDetailFragment]. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This activity also implements the required | 
					
						
							|  |  |  |  * [ListSelectionListener] interface | 
					
						
							|  |  |  |  * to listen for item selections. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private var active: Boolean = false | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Whether or not the activity is in two-pane mode, i.e. running on a tablet | 
					
						
							|  |  |  |      * device. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     var hasDetailPane: Boolean = false | 
					
						
							|  |  |  |         private set | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private lateinit var bmc: BitmessageContext | 
					
						
							|  |  |  |     private lateinit var accountHeader: AccountHeader | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private lateinit var drawer: Drawer | 
					
						
							|  |  |  |     private lateinit var nodeSwitch: SwitchDrawerItem | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-22 20:29:23 +02:00
										 |  |  |     val floatingActionButton: FabSpeedDial? | 
					
						
							| 
									
										
										
										
											2017-10-31 07:50:57 +01:00
										 |  |  |         get() = findViewById(R.id.fab) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     override fun onCreate(savedInstanceState: Bundle?) { | 
					
						
							|  |  |  |         super.onCreate(savedInstanceState) | 
					
						
							|  |  |  |         instance = WeakReference(this) | 
					
						
							|  |  |  |         bmc = Singleton.getBitmessageContext(this) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         setContentView(R.layout.activity_main) | 
					
						
							|  |  |  |         fab.hide() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-31 07:50:57 +01:00
										 |  |  |         val toolbar = findViewById<Toolbar>(R.id.toolbar) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         setSupportActionBar(toolbar) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         val listFragment = MessageListFragment() | 
					
						
							|  |  |  |         supportFragmentManager | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |             .beginTransaction() | 
					
						
							|  |  |  |             .replace(R.id.item_list, listFragment) | 
					
						
							|  |  |  |             .commit() | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-31 07:50:57 +01:00
										 |  |  |         if (findViewById<View>(R.id.message_detail_container) != null) { | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |             // The detail container view will be present only in the
 | 
					
						
							|  |  |  |             // large-screen layouts (res/values-large and
 | 
					
						
							|  |  |  |             // res/values-sw600dp). If this view is present, then the
 | 
					
						
							|  |  |  |             // activity should be in two-pane mode.
 | 
					
						
							|  |  |  |             hasDetailPane = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // In two-pane mode, list items should be given the
 | 
					
						
							|  |  |  |             // 'activated' state when touched.
 | 
					
						
							|  |  |  |             listFragment.setActivateOnItemClick(true) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         createDrawer(toolbar) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // handle intents
 | 
					
						
							|  |  |  |         val intent = intent | 
					
						
							|  |  |  |         if (intent.hasExtra(EXTRA_SHOW_MESSAGE)) { | 
					
						
							|  |  |  |             onItemSelected(intent.getSerializableExtra(EXTRA_SHOW_MESSAGE)) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (intent.hasExtra(EXTRA_REPLY_TO_MESSAGE)) { | 
					
						
							|  |  |  |             val item = intent.getSerializableExtra(EXTRA_REPLY_TO_MESSAGE) as Plaintext | 
					
						
							|  |  |  |             ComposeMessageActivity.launchReplyTo(this, item) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Preferences.useTrustedNode(this)) { | 
					
						
							|  |  |  |             SyncAdapter.startSync(this) | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             SyncAdapter.stopSync(this) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (drawer.isDrawerOpen) { | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |             val lps = RelativeLayout.LayoutParams( | 
					
						
							|  |  |  |                 ViewGroup | 
					
						
							|  |  |  |                     .LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT | 
					
						
							|  |  |  |             ).apply { | 
					
						
							|  |  |  |                 addRule(RelativeLayout.ALIGN_PARENT_BOTTOM) | 
					
						
							|  |  |  |                 addRule(RelativeLayout.ALIGN_PARENT_LEFT) | 
					
						
							|  |  |  |                 val margin = ((resources.displayMetrics.density * 12) as Number).toInt() | 
					
						
							|  |  |  |                 setMargins(margin, margin, margin, margin) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             ShowcaseView.Builder(this) | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |                 .withMaterialShowcase() | 
					
						
							|  |  |  |                 .setStyle(R.style.CustomShowcaseTheme) | 
					
						
							|  |  |  |                 .setContentTitle(R.string.full_node) | 
					
						
							|  |  |  |                 .setContentText(R.string.full_node_description) | 
					
						
							|  |  |  |                 .setTarget { | 
					
						
							|  |  |  |                     val view = drawer.stickyFooter | 
					
						
							|  |  |  |                     val location = IntArray(2) | 
					
						
							|  |  |  |                     view.getLocationInWindow(location) | 
					
						
							|  |  |  |                     val x = location[0] + 7 * view.width / 8 | 
					
						
							|  |  |  |                     val y = location[1] + view.height / 2 | 
					
						
							|  |  |  |                     Point(x, y) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 .replaceEndButton(R.layout.showcase_button) | 
					
						
							|  |  |  |                 .hideOnTouchOutside() | 
					
						
							|  |  |  |                 .build() | 
					
						
							|  |  |  |                 .setButtonPosition(lps) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private fun <F> changeList(listFragment: F) where F : Fragment, F : ListHolder<*> { | 
					
						
							|  |  |  |         if (active) { | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |             val transaction = supportFragmentManager.beginTransaction() | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |             transaction.replace(R.id.item_list, listFragment) | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |             supportFragmentManager.findFragmentById(R.id.message_detail_container)?.let { | 
					
						
							|  |  |  |                 transaction.remove(it) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             transaction.addToBackStack(null).commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (hasDetailPane) { | 
					
						
							|  |  |  |                 // In two-pane mode, list items should be given the
 | 
					
						
							|  |  |  |                 // 'activated' state when touched.
 | 
					
						
							|  |  |  |                 listFragment.setActivateOnItemClick(true) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private fun createDrawer(toolbar: Toolbar) { | 
					
						
							|  |  |  |         val profiles = ArrayList<IProfile<*>>() | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |         profiles.add( | 
					
						
							|  |  |  |             ProfileSettingDrawerItem() | 
					
						
							|  |  |  |                 .withName(getString(R.string.add_identity)) | 
					
						
							|  |  |  |                 .withDescription(getString(R.string.add_identity_summary)) | 
					
						
							|  |  |  |                 .withIcon( | 
					
						
							|  |  |  |                     IconicsDrawable(this, GoogleMaterial.Icon.gmd_add) | 
					
						
							|  |  |  |                         .actionBar() | 
					
						
							|  |  |  |                         .paddingDp(5) | 
					
						
							|  |  |  |                         .colorRes(R.color.icons) | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |                 .withIdentifier(ADD_IDENTITY.toLong()) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |         profiles.add( | 
					
						
							|  |  |  |             ProfileSettingDrawerItem() | 
					
						
							|  |  |  |                 .withName(getString(R.string.manage_identity)) | 
					
						
							|  |  |  |                 .withIcon(GoogleMaterial.Icon.gmd_settings) | 
					
						
							|  |  |  |                 .withIdentifier(MANAGE_IDENTITY.toLong()) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         ) | 
					
						
							|  |  |  |         // Create the AccountHeader
 | 
					
						
							|  |  |  |         accountHeader = AccountHeaderBuilder() | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |             .withActivity(this) | 
					
						
							|  |  |  |             .withHeaderBackground(R.drawable.header) | 
					
						
							|  |  |  |             .withProfiles(profiles) | 
					
						
							|  |  |  |             .withOnAccountHeaderProfileImageListener(ProfileImageListener(this)) | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |             .withOnAccountHeaderListener( | 
					
						
							|  |  |  |                 ProfileSelectionListener( | 
					
						
							|  |  |  |                     this@MainActivity, | 
					
						
							|  |  |  |                     supportFragmentManager | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |             .build() | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         if (profiles.size > 2) { // There's always the add and manage identity items
 | 
					
						
							|  |  |  |             accountHeader.setActiveProfile(profiles[0], true) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         val drawerItems = ArrayList<IDrawerItem<*, *>>() | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |         drawerItems.add( | 
					
						
							|  |  |  |             PrimaryDrawerItem() | 
					
						
							|  |  |  |                 .withIdentifier(LABEL_ARCHIVE.id as Long) | 
					
						
							|  |  |  |                 .withName(R.string.archive) | 
					
						
							|  |  |  |                 .withTag(LABEL_ARCHIVE) | 
					
						
							|  |  |  |                 .withIcon(CommunityMaterial.Icon.cmd_archive) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         ) | 
					
						
							|  |  |  |         drawerItems.add(DividerDrawerItem()) | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |         drawerItems.add( | 
					
						
							|  |  |  |             PrimaryDrawerItem() | 
					
						
							|  |  |  |                 .withName(R.string.contacts_and_subscriptions) | 
					
						
							|  |  |  |                 .withIcon(GoogleMaterial.Icon.gmd_contacts) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         drawerItems.add( | 
					
						
							|  |  |  |             PrimaryDrawerItem() | 
					
						
							|  |  |  |                 .withName(R.string.settings) | 
					
						
							|  |  |  |                 .withIcon(GoogleMaterial.Icon.gmd_settings) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         nodeSwitch = SwitchDrawerItem() | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |             .withIdentifier(ID_NODE_SWITCH) | 
					
						
							|  |  |  |             .withName(R.string.full_node) | 
					
						
							|  |  |  |             .withIcon(CommunityMaterial.Icon.cmd_cloud_outline) | 
					
						
							|  |  |  |             .withChecked(Preferences.isFullNodeActive(this)) | 
					
						
							|  |  |  |             .withOnCheckedChangeListener { _, _, isChecked -> | 
					
						
							|  |  |  |                 if (isChecked) { | 
					
						
							|  |  |  |                     NetworkUtils.enableNode(this@MainActivity) | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     NetworkUtils.disableNode(this@MainActivity) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         drawer = DrawerBuilder() | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |             .withActivity(this) | 
					
						
							|  |  |  |             .withToolbar(toolbar) | 
					
						
							|  |  |  |             .withAccountHeader(accountHeader) | 
					
						
							|  |  |  |             .withDrawerItems(drawerItems) | 
					
						
							|  |  |  |             .addStickyDrawerItems(nodeSwitch) | 
					
						
							|  |  |  |             .withOnDrawerItemClickListener(DrawerItemClickListener()) | 
					
						
							|  |  |  |             .withShowDrawerOnFirstLaunch(true) | 
					
						
							|  |  |  |             .build() | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         loadDrawerItemsAsynchronously() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private fun loadDrawerItemsAsynchronously() { | 
					
						
							|  |  |  |         doAsync { | 
					
						
							|  |  |  |             val identities = bmc.addresses.getIdentities() | 
					
						
							|  |  |  |             if (identities.isEmpty()) { | 
					
						
							|  |  |  |                 // Create an initial identity
 | 
					
						
							|  |  |  |                 Singleton.getIdentity(this@MainActivity) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             uiThread { | 
					
						
							|  |  |  |                 for (identity in identities) { | 
					
						
							|  |  |  |                     addIdentityEntry(identity) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         doAsync { | 
					
						
							| 
									
										
										
										
											2017-11-27 22:06:25 +01:00
										 |  |  |             val labels = bmc.labels.getLabels() | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             uiThread { | 
					
						
							|  |  |  |                 if (intent.hasExtra(EXTRA_SHOW_LABEL)) { | 
					
						
							| 
									
										
										
										
											2018-01-13 21:59:20 +01:00
										 |  |  |                     currentLabel.value = intent.getSerializableExtra(EXTRA_SHOW_LABEL) as Label | 
					
						
							|  |  |  |                 } else if (currentLabel.value == null) { | 
					
						
							|  |  |  |                     currentLabel.value = labels[0] | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 for (label in labels) { | 
					
						
							|  |  |  |                     addLabelEntry(label) | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2018-01-13 21:59:20 +01:00
										 |  |  |                 currentLabel.value?.let { | 
					
						
							|  |  |  |                     drawer.setSelection(it.id as Long) | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |                 updateUnread() | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     override fun onBackPressed() { | 
					
						
							|  |  |  |         val listFragment = supportFragmentManager.findFragmentById(R.id.item_list) | 
					
						
							| 
									
										
										
										
											2018-01-13 21:59:20 +01:00
										 |  |  |         if (listFragment !is ListHolder<*> || !listFragment.showPreviousList()) { | 
					
						
							|  |  |  |             super.onBackPressed() | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private inner class DrawerItemClickListener : Drawer.OnDrawerItemClickListener { | 
					
						
							|  |  |  |         override fun onItemClick(view: View?, position: Int, item: IDrawerItem<*, *>): Boolean { | 
					
						
							|  |  |  |             val itemList = supportFragmentManager.findFragmentById(R.id.item_list) | 
					
						
							|  |  |  |             val tag = item.tag | 
					
						
							|  |  |  |             if (tag is Label) { | 
					
						
							| 
									
										
										
										
											2018-01-13 21:59:20 +01:00
										 |  |  |                 currentLabel.value = tag | 
					
						
							|  |  |  |                 if (itemList !is MessageListFragment) { | 
					
						
							|  |  |  |                     changeList(MessageListFragment()) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 return false | 
					
						
							|  |  |  |             } else if (item is Nameable<*>) { | 
					
						
							|  |  |  |                 when (item.name.textRes) { | 
					
						
							|  |  |  |                     R.string.contacts_and_subscriptions -> { | 
					
						
							|  |  |  |                         if (itemList is AddressListFragment) { | 
					
						
							|  |  |  |                             itemList.updateList() | 
					
						
							|  |  |  |                         } else { | 
					
						
							|  |  |  |                             changeList(AddressListFragment()) | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         return false | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     R.string.settings -> { | 
					
						
							|  |  |  |                         supportFragmentManager | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |                             .beginTransaction() | 
					
						
							|  |  |  |                             .replace(R.id.item_list, SettingsFragment()) | 
					
						
							|  |  |  |                             .addToBackStack(null) | 
					
						
							|  |  |  |                             .commit() | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |                         return false | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     R.string.full_node -> return true | 
					
						
							|  |  |  |                     else -> return false | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return false | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     override fun onResume() { | 
					
						
							|  |  |  |         updateUnread() | 
					
						
							|  |  |  |         if (Preferences.isFullNodeActive(this) && Preferences.isConnectionAllowed(this@MainActivity)) { | 
					
						
							|  |  |  |             NetworkUtils.enableNode(this, false) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Singleton.getMessageListener(this).resetNotification() | 
					
						
							| 
									
										
										
										
											2018-01-13 21:59:20 +01:00
										 |  |  |         currentLabel.addObserver(this) { label -> | 
					
						
							| 
									
										
										
										
											2018-01-18 22:16:55 +01:00
										 |  |  |             if (label != null && label.id is Long) { | 
					
						
							| 
									
										
										
										
											2018-01-13 21:59:20 +01:00
										 |  |  |                 drawer.setSelection(label.id as Long) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         active = true | 
					
						
							|  |  |  |         super.onResume() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     override fun onPause() { | 
					
						
							| 
									
										
										
										
											2018-01-13 21:59:20 +01:00
										 |  |  |         currentLabel.removeObserver(this) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         super.onPause() | 
					
						
							|  |  |  |         active = false | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fun addIdentityEntry(identity: BitmessageAddress) { | 
					
						
							|  |  |  |         val newProfile = ProfileDrawerItem() | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |             .withIcon(Identicon(identity)) | 
					
						
							|  |  |  |             .withName(identity.toString()) | 
					
						
							|  |  |  |             .withNameShown(true) | 
					
						
							|  |  |  |             .withEmail(identity.address) | 
					
						
							|  |  |  |             .withTag(identity) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         if (accountHeader.profiles != null) { | 
					
						
							|  |  |  |             // we know that there are 2 setting elements.
 | 
					
						
							|  |  |  |             // Set the new profile above them ;)
 | 
					
						
							|  |  |  |             accountHeader.addProfile( | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |                 newProfile, accountHeader.profiles.size - 2 | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             accountHeader.addProfiles(newProfile) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private fun addLabelEntry(label: Label) { | 
					
						
							|  |  |  |         val item = PrimaryDrawerItem() | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |             .withIdentifier(label.id as Long) | 
					
						
							|  |  |  |             .withName(label.toString()) | 
					
						
							|  |  |  |             .withTag(label) | 
					
						
							|  |  |  |             .withIcon(Labels.getIcon(label)) | 
					
						
							|  |  |  |             .withIconColor(Labels.getColor(label)) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         drawer.addItemAtPosition(item, drawer.drawerItems.size - 3) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fun updateIdentityEntry(identity: BitmessageAddress) { | 
					
						
							|  |  |  |         for (profile in accountHeader.profiles) { | 
					
						
							|  |  |  |             if (profile is ProfileDrawerItem) { | 
					
						
							|  |  |  |                 if (identity == profile.tag) { | 
					
						
							|  |  |  |                     profile | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |                         .withName(identity.toString()) | 
					
						
							|  |  |  |                         .withTag(identity) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |                     return | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fun removeIdentityEntry(identity: BitmessageAddress) { | 
					
						
							|  |  |  |         for (profile in accountHeader.profiles) { | 
					
						
							|  |  |  |             if (profile is ProfileDrawerItem) { | 
					
						
							|  |  |  |                 if (identity == profile.tag) { | 
					
						
							|  |  |  |                     accountHeader.removeProfile(profile) | 
					
						
							|  |  |  |                     return | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fun updateUnread() { | 
					
						
							|  |  |  |         for (item in drawer.drawerItems) { | 
					
						
							|  |  |  |             if (item.tag is Label) { | 
					
						
							|  |  |  |                 val label = item.tag as Label | 
					
						
							|  |  |  |                 if (label !== LABEL_ARCHIVE) { | 
					
						
							|  |  |  |                     val unread = bmc.messages.countUnread(label) | 
					
						
							|  |  |  |                     if (unread > 0) { | 
					
						
							|  |  |  |                         (item as PrimaryDrawerItem).withBadge(unread.toString()) | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         (item as PrimaryDrawerItem).withBadge(null as String?) | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     drawer.updateItem(item) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Callback method from [ListSelectionListener] | 
					
						
							|  |  |  |      * indicating that the item with the given ID was selected. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     override fun onItemSelected(item: Serializable) { | 
					
						
							|  |  |  |         if (hasDetailPane) { | 
					
						
							|  |  |  |             // In two-pane mode, show the detail view in this activity by
 | 
					
						
							|  |  |  |             // adding or replacing the detail fragment using a
 | 
					
						
							|  |  |  |             // fragment transaction.
 | 
					
						
							|  |  |  |             val fragment = when (item) { | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |                 is Plaintext -> { | 
					
						
							|  |  |  |                     if (item.labels.any { it.type == Label.Type.DRAFT }) { | 
					
						
							|  |  |  |                         ComposeMessageFragment().apply { | 
					
						
							|  |  |  |                             arguments = Bundle().apply { | 
					
						
							|  |  |  |                                 putSerializable(ComposeMessageActivity.EXTRA_DRAFT, item) | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         MessageDetailFragment().apply { | 
					
						
							|  |  |  |                             arguments = Bundle().apply { | 
					
						
							|  |  |  |                                 putSerializable(MessageDetailFragment.ARG_ITEM, item) | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 is BitmessageAddress -> { | 
					
						
							|  |  |  |                     AddressDetailFragment().apply { | 
					
						
							|  |  |  |                         arguments = Bundle().apply { | 
					
						
							|  |  |  |                             putSerializable(AddressDetailFragment.ARG_ITEM, item) | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |                 else -> throw IllegalArgumentException("Plaintext or BitmessageAddress expected, but was ${item::class.simpleName}") | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             supportFragmentManager.beginTransaction() | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |                 .replace(R.id.message_detail_container, fragment) | 
					
						
							|  |  |  |                 .commit() | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             // In single-pane mode, simply start the detail activity
 | 
					
						
							|  |  |  |             // for the selected item ID.
 | 
					
						
							|  |  |  |             val detailIntent = when (item) { | 
					
						
							|  |  |  |                 is Plaintext -> { | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |                     if (item.labels.any { it.type == Label.Type.DRAFT }) { | 
					
						
							|  |  |  |                         Intent(this, ComposeMessageActivity::class.java).apply { | 
					
						
							|  |  |  |                             putExtra(ComposeMessageActivity.EXTRA_DRAFT, item) | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         Intent(this, MessageDetailActivity::class.java).apply { | 
					
						
							|  |  |  |                             putExtra(MessageDetailFragment.ARG_ITEM, item) | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 is BitmessageAddress -> Intent(this, AddressDetailActivity::class.java).apply { | 
					
						
							|  |  |  |                     putExtra(AddressDetailFragment.ARG_ITEM, item) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 else -> throw IllegalArgumentException("Plaintext or BitmessageAddress expected, but was ${item::class.simpleName}") | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             startActivity(detailIntent) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fun setDetailView(fragment: Fragment) { | 
					
						
							|  |  |  |         if (hasDetailPane) { | 
					
						
							| 
									
										
										
										
											2018-02-20 16:40:03 +01:00
										 |  |  |             supportFragmentManager | 
					
						
							|  |  |  |                 .beginTransaction() | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |                 .replace(R.id.message_detail_container, fragment) | 
					
						
							|  |  |  |                 .commit() | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fun updateTitle(title: CharSequence) { | 
					
						
							|  |  |  |         supportActionBar?.title = title | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     companion object { | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |         const val EXTRA_SHOW_MESSAGE = "ch.dissem.abit.ShowMessage" | 
					
						
							|  |  |  |         const val EXTRA_SHOW_LABEL = "ch.dissem.abit.ShowLabel" | 
					
						
							|  |  |  |         const val EXTRA_REPLY_TO_MESSAGE = "ch.dissem.abit.ReplyToMessage" | 
					
						
							|  |  |  |         const val ACTION_SHOW_INBOX = "ch.dissem.abit.ShowInbox" | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |         const val ADD_IDENTITY = 1 | 
					
						
							|  |  |  |         const val MANAGE_IDENTITY = 2 | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 07:24:24 +01:00
										 |  |  |         private const val ID_NODE_SWITCH: Long = 1 | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         private var instance: WeakReference<MainActivity>? = null | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fun updateNodeSwitch() { | 
					
						
							| 
									
										
										
										
											2018-01-11 17:25:26 +01:00
										 |  |  |             apply { | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |                 runOnUiThread { | 
					
						
							| 
									
										
										
										
											2017-12-30 19:21:25 +01:00
										 |  |  |                     nodeSwitch.withChecked(Preferences.isFullNodeActive(this)) | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |                     drawer.updateStickyFooterItem(nodeSwitch) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-11 17:25:26 +01:00
										 |  |  |         /** | 
					
						
							|  |  |  |          * Runs the given code in the main activity context, if it currently exists. Otherwise, | 
					
						
							|  |  |  |          * it's ignored. | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2018-01-13 21:59:20 +01:00
										 |  |  |         fun apply(run: MainActivity.() -> Unit) { | 
					
						
							| 
									
										
										
										
											2018-01-11 17:25:26 +01:00
										 |  |  |             instance?.get()?.let { run.invoke(it) } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-08-25 20:24:25 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } |