diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt index bf52cee62d19e1ef43a61de3f8d00b3c0dadea8b..9a7ef3470d60790a272022def0b95c62e1831dbc 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt @@ -24,9 +24,16 @@ import android.arch.lifecycle.Observer import android.content.Context import android.content.Intent import android.content.SharedPreferences +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Typeface +import android.graphics.drawable.Drawable import android.os.Build import android.os.Bundle import android.support.design.widget.BottomSheetBehavior +import android.support.v4.content.pm.ShortcutInfoCompat +import android.support.v4.content.pm.ShortcutManagerCompat +import android.support.v4.graphics.drawable.IconCompat import android.support.v4.widget.DrawerLayout import android.support.v7.app.ActionBarDrawerToggle import android.support.v7.widget.DefaultItemAnimator @@ -39,6 +46,8 @@ import android.widget.EditText import butterknife.BindView import butterknife.ButterKnife import com.afollestad.materialdialogs.MaterialDialog +import com.bumptech.glide.request.target.SimpleTarget +import com.bumptech.glide.request.transition.Transition import de.kuschku.libquassel.connection.ConnectionState import de.kuschku.libquassel.connection.QuasselSecurityException import de.kuschku.libquassel.protocol.Buffer_Type @@ -51,6 +60,8 @@ import de.kuschku.libquassel.util.flag.and import de.kuschku.libquassel.util.flag.hasFlag import de.kuschku.libquassel.util.flag.or import de.kuschku.libquassel.util.helpers.value +import de.kuschku.libquassel.util.irc.SenderColorUtil +import de.kuschku.quasseldroid.GlideApp import de.kuschku.quasseldroid.Keys import de.kuschku.quasseldroid.R import de.kuschku.quasseldroid.persistence.AccountDatabase @@ -64,6 +75,7 @@ import de.kuschku.quasseldroid.ui.clientsettings.client.ClientSettingsActivity import de.kuschku.quasseldroid.ui.coresettings.CoreSettingsActivity import de.kuschku.quasseldroid.ui.setup.accounts.selection.AccountSelectionActivity import de.kuschku.quasseldroid.ui.setup.user.UserSetupActivity +import de.kuschku.quasseldroid.util.avatars.AvatarHelper import de.kuschku.quasseldroid.util.helper.* import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer import de.kuschku.quasseldroid.util.missingfeatures.MissingFeaturesDialog @@ -71,6 +83,8 @@ import de.kuschku.quasseldroid.util.missingfeatures.RequiredFeatures import de.kuschku.quasseldroid.util.service.ServiceBoundActivity import de.kuschku.quasseldroid.util.ui.DragInterceptBottomSheetBehavior import de.kuschku.quasseldroid.util.ui.MaterialContentLoadingProgressBar +import de.kuschku.quasseldroid.util.ui.TextDrawable +import de.kuschku.quasseldroid.viewmodel.EditorViewModel import de.kuschku.quasseldroid.viewmodel.data.BufferData import org.threeten.bp.Instant import org.threeten.bp.ZoneId @@ -134,6 +148,17 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc intent.hasExtra(KEY_BUFFER_ID) -> { viewModel.buffer.onNext(intent.getIntExtra(KEY_BUFFER_ID, -1)) drawerLayout.closeDrawers() + if (intent.hasExtra(KEY_ACCOUNT_ID)) { + val accountId = intent.getLongExtra(ChatActivity.KEY_ACCOUNT_ID, -1) + if (accountId != this.accountId) { + resetAccount() + connectToAccount(accountId) + startedSelection = false + connectedAccount = -1L + checkConnection() + recreate() + } + } } intent.hasExtra(KEY_AUTOCOMPLETE_TEXT) -> { chatlineFragment?.editorHelper?.appendText( @@ -529,8 +554,6 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc invalidateOptionsMenu() }) - onNewIntent(intent) - editorBottomSheet = DragInterceptBottomSheetBehavior.from(chatlineFragment?.view) editorBottomSheet.state = BottomSheetBehavior.STATE_COLLAPSED chatlineFragment?.panelSlideListener?.let(editorBottomSheet::setBottomSheetCallback) @@ -547,6 +570,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc } } ) + + onNewIntent(intent) } var bufferData: BufferData? = null @@ -621,6 +646,10 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc menuInflater.inflate(R.menu.activity_main, menu) menu?.findItem(R.id.action_nicklist)?.isVisible = bufferData?.info?.type?.hasFlag(Buffer_Type.ChannelBuffer) ?: false menu?.findItem(R.id.action_filter_messages)?.isVisible = bufferData != null + menu?.findItem(R.id.action_create_shortcut)?.isVisible = + (bufferData?.info?.type?.hasFlag(Buffer_Type.ChannelBuffer) ?: false || + bufferData?.info?.type?.hasFlag(Buffer_Type.QueryBuffer) ?: false) && + Build.VERSION.SDK_INT >= Build.VERSION_CODES.O menu?.retint(toolbar.context) return super.onCreateOptionsMenu(menu) } @@ -686,6 +715,93 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc } true } + R.id.action_create_shortcut -> { + bufferData?.also { data -> + data.info?.also { info -> + val callback: (IconCompat) -> Unit = { icon -> + ShortcutManagerCompat.requestPinShortcut( + this, + ShortcutInfoCompat.Builder(this, "${System.currentTimeMillis()}") + .setShortLabel(info.bufferName ?: "") + .setIcon(icon) + .setIntent( + ChatActivity.intent( + this, + bufferId = info.bufferId, + accountId = accountId + ).setAction(Intent.ACTION_VIEW) + ) + .build(), + null + ) + } + + val resultAvailable: (Drawable) -> Unit = { resource -> + val bitmap = Bitmap.createBitmap(432, 432, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + resource.setBounds(0, 0, canvas.width, canvas.height) + resource.draw(canvas) + callback(IconCompat.createWithAdaptiveBitmap(bitmap)) + } + + val senderColors = theme.styledAttributes( + R.attr.senderColor0, R.attr.senderColor1, R.attr.senderColor2, R.attr.senderColor3, + R.attr.senderColor4, R.attr.senderColor5, R.attr.senderColor6, R.attr.senderColor7, + R.attr.senderColor8, R.attr.senderColor9, R.attr.senderColorA, R.attr.senderColorB, + R.attr.senderColorC, R.attr.senderColorD, R.attr.senderColorE, R.attr.senderColorF + ) { + IntArray(length()) { + getColor(it, 0) + } + } + + val colorBackground = theme.styledAttributes(R.attr.colorBackground) { + getColor(0, 0) + } + + if (info.type.hasFlag(Buffer_Type.QueryBuffer)) { + val nickName = info.bufferName ?: "" + val senderColorIndex = SenderColorUtil.senderColor(nickName) + val rawInitial = nickName.trimStart(*EditorViewModel.IGNORED_CHARS).firstOrNull() + ?: nickName.firstOrNull() + val initial = rawInitial?.toUpperCase().toString() + val senderColor = senderColors[senderColorIndex] + + val fallback = TextDrawable.builder() + .beginConfig() + .textColor((colorBackground and 0xFFFFFF) or (0x8A shl 24)) + .useFont(Typeface.DEFAULT_BOLD) + .endConfig() + .buildRect(initial, senderColor) + + val urls = viewModel.networks.value?.get(info.networkId)?.ircUser(info.bufferName)?.let { + AvatarHelper.avatar(messageSettings, it, 432) + } + + if (urls == null || urls.isEmpty()) { + resultAvailable(fallback) + } else { + GlideApp.with(this) + .loadWithFallbacks(urls) + ?.placeholder(fallback) + ?.into(object : SimpleTarget<Drawable>(432, 432) { + override fun onResourceReady(resource: Drawable, + transition: Transition<in Drawable>?) { + resultAvailable(resource) + } + + override fun onLoadFailed(errorDrawable: Drawable?) { + resultAvailable(errorDrawable!!) + } + }) + } + } else { + callback(IconCompat.createWithResource(this, R.drawable.ic_shortcut_channel)) + } + } + } + true + } R.id.action_core_settings -> { CoreSettingsActivity.launch(this) true @@ -736,14 +852,17 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc } } + private fun resetAccount() { + startedSelection = true + connectedAccount = -1L + restoredDrawerState = false + viewModel.resetAccount() + } + override fun onSelectAccount() { if (!startedSelection) { startActivityForResult(AccountSelectionActivity.intent(this), REQUEST_SELECT_ACCOUNT) - startedSelection = true - drawerLayout.closeDrawers() - connectedAccount = -1L - restoredDrawerState = false - viewModel.resetAccount() + resetAccount() } } @@ -752,6 +871,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc private const val KEY_AUTOCOMPLETE_TEXT = "autocomplete_text" private const val KEY_AUTOCOMPLETE_SUFFIX = "autocomplete_suffix" private const val KEY_BUFFER_ID = "buffer_id" + private const val KEY_ACCOUNT_ID = "account_id" // Instance state keys private const val KEY_OPEN_BUFFER = "open_buffer" @@ -765,7 +885,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc sharedText: CharSequence? = null, autoCompleteText: CharSequence? = null, autoCompleteSuffix: String? = null, - bufferId: Int? = null + bufferId: Int? = null, + accountId: Int? = null ) = context.startActivity( intent(context, sharedText, autoCompleteText, autoCompleteSuffix, bufferId) ) @@ -775,7 +896,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc sharedText: CharSequence? = null, autoCompleteText: CharSequence? = null, autoCompleteSuffix: String? = null, - bufferId: Int? = null + bufferId: Int? = null, + accountId: Long? = null ) = Intent(context, ChatActivity::class.java).apply { if (sharedText != null) { type = "text/plain" @@ -789,6 +911,9 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc } if (bufferId != null) { putExtra(KEY_BUFFER_ID, bufferId) + if (accountId != null) { + putExtra(KEY_ACCOUNT_ID, accountId) + } } } } diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt index b9c355097f96ed0ed5db92a2b41e15fdb5de02c0..c8f062998890b860fbebeaea5165c3c5b7a9d5b3 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/util/service/ServiceBoundActivity.kt @@ -31,6 +31,7 @@ import de.kuschku.quasseldroid.Keys import de.kuschku.quasseldroid.R import de.kuschku.quasseldroid.settings.ConnectionSettings import de.kuschku.quasseldroid.settings.Settings +import de.kuschku.quasseldroid.util.helper.editCommit import de.kuschku.quasseldroid.util.helper.sharedPreferences import de.kuschku.quasseldroid.util.helper.updateRecentsHeaderIfExisting import de.kuschku.quasseldroid.util.ui.ThemedActivity @@ -61,6 +62,16 @@ abstract class ServiceBoundActivity : } } + fun connectToAccount(accountId: Long) { + getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE).editCommit { + putBoolean(Keys.Status.reconnect, false) + } + getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE).editCommit { + putLong(Keys.Status.selectedAccount, accountId) + putBoolean(Keys.Status.reconnect, true) + } + } + @Inject lateinit var connectionSettings: ConnectionSettings @@ -116,7 +127,7 @@ abstract class ServiceBoundActivity : override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) = checkConnection() - private fun checkConnection() { + protected fun checkConnection() { accountId = getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE) ?.getLong(Keys.Status.selectedAccount, -1) ?: -1 diff --git a/app/src/main/res/drawable/ic_shortcut_channel.xml b/app/src/main/res/drawable/ic_shortcut_channel.xml index 352d0224254f50dfa6b04fb86d461c089a0e0728..7526d6ece3c7465bd020ee2271128f535b2731c3 100644 --- a/app/src/main/res/drawable/ic_shortcut_channel.xml +++ b/app/src/main/res/drawable/ic_shortcut_channel.xml @@ -18,6 +18,6 @@ --> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> - <background android:drawable="@color/colorPrimaryDark" /> + <background android:drawable="@color/colorAccent" /> <foreground android:drawable="@drawable/ic_shortcut_channel_foreground" /> </adaptive-icon> diff --git a/app/src/main/res/menu/activity_main.xml b/app/src/main/res/menu/activity_main.xml index 1c68935106a184faaf1b74761effaaea9c0e025e..8ab71efc1f93965456d9acaf5c869551a5330c6c 100644 --- a/app/src/main/res/menu/activity_main.xml +++ b/app/src/main/res/menu/activity_main.xml @@ -27,6 +27,9 @@ <item android:id="@+id/action_filter_messages" android:title="@string/label_filter_messages" /> + <item + android:id="@+id/action_create_shortcut" + android:title="@string/label_create_shortcut" /> <item android:id="@+id/action_core_settings" android:title="@string/label_settings_core" /> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 9bd70f4ccd4238df3648045949874e2baaa064a3..4f836483325cc2e84deadb2c0a2eabd7e10e8f74 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -41,6 +41,7 @@ <string name="label_contributors">Mitwirkende</string> <string name="label_copy">Kopieren</string> <string name="label_crashes">Absturzberichte</string> + <string name="label_create_shortcut">Verknüpfung erstellen</string> <string name="label_delete">Löschen</string> <string name="label_delete_all">Alle Löschen</string> <string name="label_disconnect">Verbindung trennen</string> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 28f2d180a4b4c6c085bb25120a6878b4cc9a2b4c..866485c57d1cb4fbc57487f9249749b2e1ac107b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -43,6 +43,7 @@ <string name="label_contributors">Contributors</string> <string name="label_copy">Copy</string> <string name="label_crashes">Crashes</string> + <string name="label_create_shortcut">Create Shortcut</string> <string name="label_delete">Delete</string> <string name="label_delete_all">Delete All</string> <string name="label_disconnect">Disconnect</string>