From cd69679e9aa1b7895763b7d089c700d332bef18c Mon Sep 17 00:00:00 2001 From: Adolfo Santiago Date: Sun, 8 May 2022 09:40:21 +0200 Subject: [PATCH] Hide username in Live Notifications push This change will allow you to hide your name in the permanent notification. --- husky/app/src/husky/res/values/strings.xml | 4 + .../com/keylesspalace/tusky/MainActivity.kt | 67 +++++++++++-- .../preference/PreferencesFragment.kt | 26 +++++ .../tusky/service/StreamingService.kt | 94 +++++++++++-------- .../tusky/settings/SettingsConstants.kt | 1 + .../app/src/main/res/xml/app_preferences.xml | 9 ++ 6 files changed, 155 insertions(+), 46 deletions(-) diff --git a/husky/app/src/husky/res/values/strings.xml b/husky/app/src/husky/res/values/strings.xml index 1cbda48..ffbaa3f 100644 --- a/husky/app/src/husky/res/values/strings.xml +++ b/husky/app/src/husky/res/values/strings.xml @@ -44,6 +44,8 @@ Other Privacy + hideLiveNotifDesc + Composing Composing using zero-width space characters in emojis @@ -52,6 +54,8 @@ acra.enable Anonymize uploaded file names + Hide Live Notification username + This will be changed once you go back to the timeline. Live notifications May slightly increase power consumption Default formatting syntax(if supported by instance) diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt b/husky/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt index b2a00b3..512b2cd 100644 --- a/husky/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt +++ b/husky/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt @@ -53,7 +53,13 @@ import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout.OnTabSelectedListener import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator.TabConfigurationStrategy -import com.keylesspalace.tusky.appstore.* +import com.keylesspalace.tusky.appstore.AnnouncementReadEvent +import com.keylesspalace.tusky.appstore.CacheUpdater +import com.keylesspalace.tusky.appstore.Event +import com.keylesspalace.tusky.appstore.EventHub +import com.keylesspalace.tusky.appstore.MainTabsChangedEvent +import com.keylesspalace.tusky.appstore.PreferenceChangedEvent +import com.keylesspalace.tusky.appstore.ProfileEditedEvent import com.keylesspalace.tusky.components.announcements.AnnouncementsActivity import com.keylesspalace.tusky.components.compose.ComposeActivity import com.keylesspalace.tusky.components.compose.ComposeActivity.Companion.canHandleMimeType @@ -74,7 +80,14 @@ import com.keylesspalace.tusky.interfaces.ReselectableFragment import com.keylesspalace.tusky.pager.MainPagerAdapter import com.keylesspalace.tusky.service.StreamingService import com.keylesspalace.tusky.settings.PrefKeys -import com.keylesspalace.tusky.util.* +import com.keylesspalace.tusky.util.ThemeUtils +import com.keylesspalace.tusky.util.ViewPager2Fix +import com.keylesspalace.tusky.util.deleteStaleCachedMedia +import com.keylesspalace.tusky.util.emojify +import com.keylesspalace.tusky.util.hide +import com.keylesspalace.tusky.util.removeShortcut +import com.keylesspalace.tusky.util.updateShortcut +import com.keylesspalace.tusky.util.visible import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.utils.colorInt @@ -83,9 +96,27 @@ import com.mikepenz.materialdrawer.holder.BadgeStyle import com.mikepenz.materialdrawer.holder.ColorHolder import com.mikepenz.materialdrawer.holder.StringHolder import com.mikepenz.materialdrawer.iconics.iconicsIcon -import com.mikepenz.materialdrawer.model.* -import com.mikepenz.materialdrawer.model.interfaces.* -import com.mikepenz.materialdrawer.util.* +import com.mikepenz.materialdrawer.model.AbstractDrawerItem +import com.mikepenz.materialdrawer.model.DividerDrawerItem +import com.mikepenz.materialdrawer.model.PrimaryDrawerItem +import com.mikepenz.materialdrawer.model.ProfileDrawerItem +import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem +import com.mikepenz.materialdrawer.model.SecondaryDrawerItem +import com.mikepenz.materialdrawer.model.interfaces.IProfile +import com.mikepenz.materialdrawer.model.interfaces.descriptionRes +import com.mikepenz.materialdrawer.model.interfaces.descriptionText +import com.mikepenz.materialdrawer.model.interfaces.iconRes +import com.mikepenz.materialdrawer.model.interfaces.iconUrl +import com.mikepenz.materialdrawer.model.interfaces.nameRes +import com.mikepenz.materialdrawer.model.interfaces.nameText +import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader +import com.mikepenz.materialdrawer.util.DrawerImageLoader +import com.mikepenz.materialdrawer.util.addItemAtPosition +import com.mikepenz.materialdrawer.util.addItems +import com.mikepenz.materialdrawer.util.addItemsAtPosition +import com.mikepenz.materialdrawer.util.getDrawerItem +import com.mikepenz.materialdrawer.util.removeItems +import com.mikepenz.materialdrawer.util.updateBadge import com.mikepenz.materialdrawer.widget.AccountHeaderView import com.uber.autodispose.android.lifecycle.autoDispose import dagger.android.DispatchingAndroidInjector @@ -93,7 +124,14 @@ import dagger.android.HasAndroidInjector import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import javax.inject.Inject -import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.activity_main.bottomNav +import kotlinx.android.synthetic.main.activity_main.bottomTabLayout +import kotlinx.android.synthetic.main.activity_main.composeButton +import kotlinx.android.synthetic.main.activity_main.mainDrawer +import kotlinx.android.synthetic.main.activity_main.mainDrawerLayout +import kotlinx.android.synthetic.main.activity_main.mainToolbar +import kotlinx.android.synthetic.main.activity_main.tabLayout +import kotlinx.android.synthetic.main.activity_main.viewPager import timber.log.Timber class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInjector { @@ -237,6 +275,9 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje PrefKeys.LIVE_NOTIFICATIONS -> { initPullNotifications() } + PrefKeys.HIDE_LIVE_NOTIFICATION_DESCRIPTION -> { + initPullNotifications(rebootPush = true) + } } } is AnnouncementReadEvent -> { @@ -259,7 +300,11 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje ) } - private fun initPullNotifications() { + private fun initPullNotifications(rebootPush: Boolean = false) { + if(rebootPush) { + disablePushNotifications() + } + if(NotificationHelper.areNotificationsEnabled(this, accountManager)) { if(accountManager.areNotificationsStreamingEnabled()) { StreamingService.startStreaming(this) @@ -269,12 +314,16 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje NotificationHelper.enablePullNotifications(this) } } else { - StreamingService.stopStreaming(this) - NotificationHelper.disablePullNotifications(this) + disablePushNotifications() } draftWarning() } + private fun disablePushNotifications() { + StreamingService.stopStreaming(this) + NotificationHelper.disablePullNotifications(this) + } + override fun onResume() { super.onResume() NotificationHelper.clearNotificationsForActiveAccount(this, accountManager) diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt b/husky/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt index a8a2124..209e042 100644 --- a/husky/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt +++ b/husky/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt @@ -21,12 +21,17 @@ package com.keylesspalace.tusky.components.preference import android.os.Bundle +import android.widget.Toast import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import com.keylesspalace.tusky.R +import com.keylesspalace.tusky.appstore.EventHub +import com.keylesspalace.tusky.appstore.PreferenceChangedEvent +import com.keylesspalace.tusky.components.notifications.NotificationHelper import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.entity.Notification +import com.keylesspalace.tusky.service.StreamingService import com.keylesspalace.tusky.settings.AppTheme import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.emojiPreference @@ -55,6 +60,9 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable { @Inject lateinit var accountManager: AccountManager + @Inject + lateinit var eventHub: EventHub + private val iconSize by lazy { resources.getDimensionPixelSize(R.dimen.preference_icon_size) } private var httpProxyPref: Preference? = null @@ -246,6 +254,24 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable { setTitle(R.string.pref_title_anonymize_upload_filenames) isSingleLineTitle = false } + + switchPreference { + setDefaultValue(false) + key = PrefKeys.HIDE_LIVE_NOTIFICATION_DESCRIPTION + setTitle(R.string.pref_title_hide_live_notification_description) + isSingleLineTitle = false + setOnPreferenceChangeListener { _, _ -> + eventHub.dispatch(PreferenceChangedEvent(key)) + + Toast.makeText( + context, + getString(R.string.pref_title_hide_live_notification_description_toast), + Toast.LENGTH_LONG + ).show() + + true + } + } } preferenceCategory(R.string.pref_title_browser_settings) { diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/service/StreamingService.kt b/husky/app/src/main/java/com/keylesspalace/tusky/service/StreamingService.kt index 16d3491..f645046 100644 --- a/husky/app/src/main/java/com/keylesspalace/tusky/service/StreamingService.kt +++ b/husky/app/src/main/java/com/keylesspalace/tusky/service/StreamingService.kt @@ -7,10 +7,10 @@ import android.content.Context import android.content.Intent import android.os.Build import android.os.IBinder -import android.util.Log import androidx.core.app.NotificationCompat import androidx.core.app.ServiceCompat import androidx.core.content.ContextCompat +import androidx.preference.PreferenceManager import com.google.gson.Gson import com.keylesspalace.tusky.R import com.keylesspalace.tusky.appstore.ChatMessageReceivedEvent @@ -22,12 +22,19 @@ import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.entity.Notification import com.keylesspalace.tusky.entity.StreamEvent import com.keylesspalace.tusky.network.MastodonApi +import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.util.isLessThan import dagger.android.AndroidInjection -import okhttp3.* import javax.inject.Inject +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okhttp3.WebSocket +import okhttp3.WebSocketListener +import timber.log.Timber + +class StreamingService : Service(), Injectable { -class StreamingService: Service(), Injectable { @Inject lateinit var api: MastodonApi @@ -58,7 +65,7 @@ class StreamingService: Service(), Injectable { private fun stopStreamingForId(id: Long) { if(id in sockets) { - sockets[id]!!.close(1000, null) + sockets[id]?.close(1000, null) sockets.remove(id) } } @@ -69,7 +76,7 @@ class StreamingService: Service(), Injectable { } sockets.clear() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH) } @@ -87,7 +94,7 @@ class StreamingService: Service(), Injectable { override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { if(intent.getBooleanExtra(KEY_STOP_STREAMING, false)) { - Log.d(TAG, "Stream goes suya..") + Timber.d("Stream goes suya..") stopStreaming() stopSelfResult(startId) return START_NOT_STICKY @@ -99,20 +106,22 @@ class StreamingService: Service(), Injectable { for(account in accounts) { stopStreamingForId(account.id) - if(!account.notificationsStreamingEnabled) + if(!account.notificationsStreamingEnabled) { continue + } - val endpoint = "wss://${account.domain}/api/v1/streaming/?access_token=${account.accessToken}&stream=user:notification" + val endpoint = + "wss://${account.domain}/api/v1/streaming/?access_token=${account.accessToken}&stream=user:notification" val request = Request.Builder().url(endpoint).build() - Log.d(TAG, "Running stream for ${account.fullName}") + Timber.d("Running stream for ${account.fullName}") sockets[account.id] = client.newWebSocket( - request, - makeStreamingListener( - "${account.fullName}/user:notification", - account - ) + request, + makeStreamingListener( + "${account.fullName}/user:notification", + account + ) ) description += "\n" + account.fullName @@ -120,27 +129,36 @@ class StreamingService: Service(), Injectable { } if(count <= 0) { - Log.d(TAG, "No accounts. Stopping stream") + Timber.d("No accounts. Stopping stream") stopStreaming() stopSelfResult(startId) return START_NOT_STICKY } - if (NotificationHelper.NOTIFICATION_USE_CHANNELS) { - val channel = NotificationChannel(CHANNEL_ID, getString(R.string.streaming_notification_name), NotificationManager.IMPORTANCE_LOW) + if(NotificationHelper.NOTIFICATION_USE_CHANNELS) { + val channel = NotificationChannel( + CHANNEL_ID, + getString(R.string.streaming_notification_name), + NotificationManager.IMPORTANCE_LOW + ) notificationManager.createNotificationChannel(channel) } val builder = NotificationCompat.Builder(this, CHANNEL_ID) - .setSmallIcon(R.drawable.ic_notify) - .setContentTitle(getString(R.string.streaming_notification_name)) - .setContentText(description) - .setOngoing(true) - .setNotificationSilent() - .setPriority(NotificationCompat.PRIORITY_MIN) - .setColor(ContextCompat.getColor(this, R.color.tusky_blue)) + .setSmallIcon(R.drawable.ic_notify) + .setContentTitle(getString(R.string.streaming_notification_name)) + .setOngoing(true) + .setSilent(true) + .setPriority(NotificationCompat.PRIORITY_MIN) + .setColor(ContextCompat.getColor(this, R.color.tusky_blue)) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val showDescription = PreferenceManager.getDefaultSharedPreferences(this) + .getBoolean(PrefKeys.HIDE_LIVE_NOTIFICATION_DESCRIPTION, false) + if(!showDescription) { + builder.setContentText(description) + } + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH) startForeground(1337, builder.build()) } else { @@ -155,9 +173,8 @@ class StreamingService: Service(), Injectable { } companion object { - val CHANNEL_ID = "streaming" - val KEY_STOP_STREAMING = "stop_streaming" - val TAG = "StreamingService" + const val CHANNEL_ID = "streaming" + const val KEY_STOP_STREAMING = "stop_streaming" @JvmStatic var serviceRunning = false @@ -176,7 +193,7 @@ class StreamingService: Service(), Injectable { val intent = Intent(context, StreamingService::class.java) intent.putExtra(KEY_STOP_STREAMING, false) - Log.d(TAG, "Starting notifications streaming service...") + Timber.d("Starting notifications streaming service...") startForegroundService(context, intent) } @@ -184,13 +201,14 @@ class StreamingService: Service(), Injectable { @JvmStatic fun stopStreaming(context: Context) { synchronized(serviceRunning) { - if(!serviceRunning) + if(!serviceRunning) { return + } val intent = Intent(context, StreamingService::class.java) intent.putExtra(KEY_STOP_STREAMING, true) - Log.d(TAG, "Stopping notifications streaming service...") + Timber.d("Stopping notifications streaming service...") serviceRunning = false @@ -199,18 +217,20 @@ class StreamingService: Service(), Injectable { } } - private fun makeStreamingListener(tag: String, account: AccountEntity) : WebSocketListener { + private fun makeStreamingListener(tag: String, account: AccountEntity): WebSocketListener { + return object : WebSocketListener() { + override fun onOpen(webSocket: WebSocket, response: Response) { - Log.d(TAG, "Stream connected to: $tag") + Timber.d("Stream connected to: $tag") } override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { - Log.d(TAG, "Stream closed for: $tag") + Timber.d("Stream closed for: $tag") } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - Log.d(TAG, "Stream failed for $tag", t) + Timber.e("Stream failed for $tag", t) } override fun onMessage(webSocket: WebSocket, text: String) { @@ -230,10 +250,10 @@ class StreamingService: Service(), Injectable { } } else -> { - Log.d(TAG, "Unknown event type: ${event.event}") + Timber.w("Unknown event type: ${event.event}") } } } } } -} \ No newline at end of file +} diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt b/husky/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt index db8bc25..5d7d307 100644 --- a/husky/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt +++ b/husky/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt @@ -54,6 +54,7 @@ object PrefKeys { const val BIG_EMOJIS = "bigEmojis" const val STICKERS = "stickers" const val ANONYMIZE_FILENAMES = "anonymizeFilenames" + const val HIDE_LIVE_NOTIFICATION_DESCRIPTION = "hideLiveNotifDesc" const val HIDE_MUTED_USERS = "hideMutedUsers" const val ANIMATE_CUSTOM_EMOJIS = "animateCustomEmojis" const val RENDER_STATUS_AS_MENTION = "renderStatusAsMention" diff --git a/husky/app/src/main/res/xml/app_preferences.xml b/husky/app/src/main/res/xml/app_preferences.xml index efa8766..8e0dac1 100644 --- a/husky/app/src/main/res/xml/app_preferences.xml +++ b/husky/app/src/main/res/xml/app_preferences.xml @@ -1,6 +1,15 @@ + + + + + +