From 274b217a56098b88d3bc96ef0427b0e29a2f88ec Mon Sep 17 00:00:00 2001 From: moezbhatti Date: Mon, 17 Jun 2019 02:17:30 -0400 Subject: [PATCH] Show changelog after app update --- .../QKSMS/manager/ChangelogManagerImpl.kt | 49 ++++++++ .../java/com/moez/QKSMS/util/Preferences.kt | 1 + .../moez/QKSMS/manager/ChangelogManager.kt | 28 +++++ .../moez/QKSMS/common/util/TextViewStyler.kt | 10 ++ .../feature/changelog/ChangelogAdapter.kt | 54 +++++++++ .../feature/changelog/ChangelogDialog.kt | 55 +++++++++ .../moez/QKSMS/feature/main/MainActivity.kt | 7 ++ .../com/moez/QKSMS/feature/main/MainView.kt | 2 + .../moez/QKSMS/feature/main/MainViewModel.kt | 11 ++ .../com/moez/QKSMS/injection/AppModule.kt | 6 + .../src/main/res/layout/changelog_dialog.xml | 109 ++++++++++++++++++ .../main/res/layout/changelog_list_item.xml | 30 +++++ presentation/src/main/res/values/attrs.xml | 1 + .../src/main/res/values/donottranslate.xml | 32 ++++- 14 files changed, 394 insertions(+), 1 deletion(-) create mode 100644 data/src/main/java/com/moez/QKSMS/manager/ChangelogManagerImpl.kt create mode 100644 domain/src/main/java/com/moez/QKSMS/manager/ChangelogManager.kt create mode 100644 presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogAdapter.kt create mode 100644 presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogDialog.kt create mode 100644 presentation/src/main/res/layout/changelog_dialog.xml create mode 100644 presentation/src/main/res/layout/changelog_list_item.xml diff --git a/data/src/main/java/com/moez/QKSMS/manager/ChangelogManagerImpl.kt b/data/src/main/java/com/moez/QKSMS/manager/ChangelogManagerImpl.kt new file mode 100644 index 00000000..d42336fa --- /dev/null +++ b/data/src/main/java/com/moez/QKSMS/manager/ChangelogManagerImpl.kt @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2017 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.manager + +import android.content.Context +import com.moez.QKSMS.model.SyncLog +import com.moez.QKSMS.util.Preferences +import io.realm.Realm +import javax.inject.Inject + +class ChangelogManagerImpl @Inject constructor( + private val context: Context, + private val prefs: Preferences +) : ChangelogManager { + + override fun didUpdate(): Boolean { + val oldVersion = prefs.version.get() + val newVersion = context.packageManager.getPackageInfo(context.packageName, 0).versionCode + val lastSync = Realm.getDefaultInstance().use { realm -> realm.where(SyncLog::class.java)?.max("date") ?: 0 } + + if (oldVersion != newVersion) { + prefs.version.set(newVersion) + } + + return when { + oldVersion == 0 && lastSync != 0 -> true // Just updated to 3.6.5. TODO: Remove this after 3.6.5 + oldVersion == 0 -> false // First install + oldVersion != newVersion -> true // Update + else -> false + } + } + +} diff --git a/data/src/main/java/com/moez/QKSMS/util/Preferences.kt b/data/src/main/java/com/moez/QKSMS/util/Preferences.kt index f2ba12f0..a13858f8 100644 --- a/data/src/main/java/com/moez/QKSMS/util/Preferences.kt +++ b/data/src/main/java/com/moez/QKSMS/util/Preferences.kt @@ -87,6 +87,7 @@ class Preferences @Inject constructor(private val rxPrefs: RxSharedPreferences) val mobileOnly = rxPrefs.getBoolean("mobileOnly", false) val mmsSize = rxPrefs.getInteger("mmsSize", 300) val logging = rxPrefs.getBoolean("logging", false) + val version = rxPrefs.getInteger("version", 0) fun theme(threadId: Long = 0): Preference { val default = rxPrefs.getInteger("theme", 0xFF0097A7.toInt()) diff --git a/domain/src/main/java/com/moez/QKSMS/manager/ChangelogManager.kt b/domain/src/main/java/com/moez/QKSMS/manager/ChangelogManager.kt new file mode 100644 index 00000000..65cf0159 --- /dev/null +++ b/domain/src/main/java/com/moez/QKSMS/manager/ChangelogManager.kt @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.manager + +interface ChangelogManager { + + /** + * Returns true if the app has benn updated since the last time this method was called + */ + fun didUpdate(): Boolean + +} diff --git a/presentation/src/main/java/com/moez/QKSMS/common/util/TextViewStyler.kt b/presentation/src/main/java/com/moez/QKSMS/common/util/TextViewStyler.kt index 92c14d5a..4ad25a18 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/util/TextViewStyler.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/util/TextViewStyler.kt @@ -52,6 +52,7 @@ class TextViewStyler @Inject constructor( const val SIZE_SECONDARY = 1 const val SIZE_TERTIARY = 2 const val SIZE_TOOLBAR = 3 + const val SIZE_DIALOG = 4 fun applyEditModeAttributes(textView: TextView, attrs: AttributeSet?) { textView.run { @@ -89,6 +90,7 @@ class TextViewStyler @Inject constructor( SIZE_SECONDARY -> 14f SIZE_TERTIARY -> 12f SIZE_TOOLBAR -> 20f + SIZE_DIALOG -> 18f else -> textSize / paint.density } } @@ -177,6 +179,14 @@ class TextViewStyler @Inject constructor( Preferences.TEXT_SIZE_LARGER -> 26f else -> 20f } + + SIZE_DIALOG -> textView.textSize = when (textSizePref) { + Preferences.TEXT_SIZE_SMALL -> 16f + Preferences.TEXT_SIZE_NORMAL -> 18f + Preferences.TEXT_SIZE_LARGE -> 20f + Preferences.TEXT_SIZE_LARGER -> 24f + else -> 18f + } } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogAdapter.kt new file mode 100644 index 00000000..27714c93 --- /dev/null +++ b/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogAdapter.kt @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.feature.changelog + +import android.graphics.Typeface +import android.view.LayoutInflater +import android.view.ViewGroup +import com.moez.QKSMS.R +import com.moez.QKSMS.common.base.QkAdapter +import com.moez.QKSMS.common.base.QkViewHolder +import kotlinx.android.synthetic.main.changelog_list_item.* + +class ChangelogAdapter(val keywords: List, data: List) : QkAdapter() { + + init { + this.data = data + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.changelog_list_item, parent, false) + return QkViewHolder(view).apply { + if (viewType == 0) { + changelogItem.setTypeface(changelogItem.typeface, Typeface.BOLD) + } + } + } + + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + val item = getItem(position) + + holder.changelogItem.text = item + } + + override fun getItemViewType(position: Int): Int { + return if (getItem(position) in keywords) 0 else 1 + } + +} diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogDialog.kt b/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogDialog.kt new file mode 100644 index 00000000..5df7077c --- /dev/null +++ b/presentation/src/main/java/com/moez/QKSMS/feature/changelog/ChangelogDialog.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.feature.changelog + +import android.view.LayoutInflater +import androidx.appcompat.app.AlertDialog +import com.moez.QKSMS.BuildConfig +import com.moez.QKSMS.R +import com.moez.QKSMS.feature.main.MainActivity +import io.reactivex.subjects.PublishSubject +import io.reactivex.subjects.Subject +import kotlinx.android.synthetic.main.changelog_dialog.view.* + +class ChangelogDialog(activity: MainActivity) { + + val moreClicks: Subject = PublishSubject.create() + + private val dialog: AlertDialog + private val adapter = ChangelogAdapter( + activity.resources.getStringArray(R.array.changelog_keywords).asList(), + activity.resources.getStringArray(R.array.changelog).asList()) + + init { + val layout = LayoutInflater.from(activity).inflate(R.layout.changelog_dialog, null) + + dialog = AlertDialog.Builder(activity) + .setCancelable(true) + .setView(layout) + .create() + + layout.version.text = activity.getString(R.string.changelog_version, BuildConfig.VERSION_NAME) + layout.changelog.adapter = adapter + layout.more.setOnClickListener { dialog.dismiss(); moreClicks.onNext(Unit) } + layout.dismiss.setOnClickListener { dialog.dismiss() } + } + + fun show() = dialog.show() + +} diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt index 5bf9728b..3d58ec99 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt @@ -52,6 +52,7 @@ import com.moez.QKSMS.common.util.extensions.scrapViews import com.moez.QKSMS.common.util.extensions.setBackgroundTint import com.moez.QKSMS.common.util.extensions.setTint import com.moez.QKSMS.common.util.extensions.setVisible +import com.moez.QKSMS.feature.changelog.ChangelogDialog import com.moez.QKSMS.feature.conversations.ConversationItemTouchCallback import com.moez.QKSMS.feature.conversations.ConversationsAdapter import com.moez.QKSMS.repository.SyncRepository @@ -105,6 +106,7 @@ class MainActivity : QkThemedActivity(), MainView { override val conversationsSelectedIntent by lazy { conversationsAdapter.selectionChanges } override val confirmDeleteIntent: Subject> = PublishSubject.create() override val swipeConversationIntent by lazy { itemTouchCallback.swipes } + override val changelogMoreIntent by lazy { changelog.moreClicks } override val undoArchiveIntent: Subject = PublishSubject.create() override val snackbarButtonIntent: Subject = PublishSubject.create() override val backPressedIntent: Subject = PublishSubject.create() @@ -113,6 +115,7 @@ class MainActivity : QkThemedActivity(), MainView { private val toggle by lazy { ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.main_drawer_open_cd, 0) } private val itemTouchHelper by lazy { ItemTouchHelper(itemTouchCallback) } private val progressAnimator by lazy { ObjectAnimator.ofInt(syncingProgress, "progress", 0, 0) } + private val changelog by lazy { ChangelogDialog(this) } private val archiveSnackbar by lazy { Snackbar.make(drawerLayout, R.string.toast_archived, Snackbar.LENGTH_LONG).apply { setAction(R.string.button_undo) { undoArchiveIntent.onNext(Unit) } @@ -344,6 +347,10 @@ class MainActivity : QkThemedActivity(), MainView { .show() } + override fun showChangelog() { + changelog.show() + } + override fun showArchivedSnackbar() { archiveSnackbar.show() } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainView.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainView.kt index f14d9f5b..fb4f8a26 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainView.kt @@ -36,6 +36,7 @@ interface MainView : QkView { val conversationsSelectedIntent: Observable> val confirmDeleteIntent: Observable> val swipeConversationIntent: Observable> + val changelogMoreIntent: Observable<*> val undoArchiveIntent: Observable val snackbarButtonIntent: Observable val backPressedIntent: Observable @@ -44,6 +45,7 @@ interface MainView : QkView { fun clearSearch() fun clearSelection() fun showDeleteDialog(conversations: List) + fun showChangelog() fun showArchivedSnackbar() } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt index 255930f4..0c22bb39 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt @@ -36,6 +36,7 @@ import com.moez.QKSMS.interactor.MarkUnpinned import com.moez.QKSMS.interactor.MarkUnread import com.moez.QKSMS.interactor.MigratePreferences import com.moez.QKSMS.interactor.SyncMessages +import com.moez.QKSMS.manager.ChangelogManager import com.moez.QKSMS.manager.PermissionManager import com.moez.QKSMS.manager.RatingManager import com.moez.QKSMS.model.SyncLog @@ -57,6 +58,7 @@ class MainViewModel @Inject constructor( markAllSeen: MarkAllSeen, migratePreferences: MigratePreferences, syncRepository: SyncRepository, + private val changelogManager: ChangelogManager, private val conversationRepo: ConversationRepository, private val deleteConversations: DeleteConversations, private val markArchived: MarkArchived, @@ -141,6 +143,15 @@ class MainViewModel @Inject constructor( .autoDisposable(view.scope()) .subscribe { syncMessages.execute(Unit) } + // Show changelog + if (changelogManager.didUpdate()) { + view.showChangelog() + } + + view.changelogMoreIntent + .autoDisposable(view.scope()) + .subscribe { navigator.showChangelog() } + view.queryChangedIntent .debounce(200, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) diff --git a/presentation/src/main/java/com/moez/QKSMS/injection/AppModule.kt b/presentation/src/main/java/com/moez/QKSMS/injection/AppModule.kt index 1bfa652f..a4a3798c 100644 --- a/presentation/src/main/java/com/moez/QKSMS/injection/AppModule.kt +++ b/presentation/src/main/java/com/moez/QKSMS/injection/AppModule.kt @@ -1,3 +1,4 @@ + /* * Copyright (C) 2017 Moez Bhatti * @@ -37,6 +38,8 @@ import com.moez.QKSMS.manager.AlarmManager import com.moez.QKSMS.manager.AlarmManagerImpl import com.moez.QKSMS.manager.AnalyticsManager import com.moez.QKSMS.manager.AnalyticsManagerImpl +import com.moez.QKSMS.manager.ChangelogManager +import com.moez.QKSMS.manager.ChangelogManagerImpl import com.moez.QKSMS.manager.ExternalBlockingManager import com.moez.QKSMS.manager.ExternalBlockingManagerImpl import com.moez.QKSMS.manager.KeyManager @@ -125,6 +128,9 @@ class AppModule(private var application: Application) { @Provides fun externalBlockingManager(manager: ExternalBlockingManagerImpl): ExternalBlockingManager = manager + @Provides + fun changelogManager(manager: ChangelogManagerImpl): ChangelogManager = manager + @Provides fun provideKeyManager(manager: KeyManagerImpl): KeyManager = manager diff --git a/presentation/src/main/res/layout/changelog_dialog.xml b/presentation/src/main/res/layout/changelog_dialog.xml new file mode 100644 index 00000000..f0595885 --- /dev/null +++ b/presentation/src/main/res/layout/changelog_dialog.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + diff --git a/presentation/src/main/res/layout/changelog_list_item.xml b/presentation/src/main/res/layout/changelog_list_item.xml new file mode 100644 index 00000000..d681a175 --- /dev/null +++ b/presentation/src/main/res/layout/changelog_list_item.xml @@ -0,0 +1,30 @@ + + + diff --git a/presentation/src/main/res/values/attrs.xml b/presentation/src/main/res/values/attrs.xml index 9677ad8f..e7c7b7e7 100644 --- a/presentation/src/main/res/values/attrs.xml +++ b/presentation/src/main/res/values/attrs.xml @@ -34,6 +34,7 @@ + diff --git a/presentation/src/main/res/values/donottranslate.xml b/presentation/src/main/res/values/donottranslate.xml index 6b164ce2..8cdfb1ee 100644 --- a/presentation/src/main/res/values/donottranslate.xml +++ b/presentation/src/main/res/values/donottranslate.xml @@ -30,4 +30,34 @@ GNU General Public License v3.0 © 2014–2018 - \ No newline at end of file + New in QKSMS + Version %s + + Added + Improved + Fixed + + + Added + - Support for latest version of Should I Answer + - New swipe action to mark a conversation unread + - Updates will now show a changelog! + + Improved + - Added unread indicator to make those conversations easier to spot + - Better support for sharing text from other apps + - Should I Answer integration will respect numbers that you have manually blocked + - Status bar for dark theme will match toolbar + - Make sure to ask to be default SMS app before attempting to perform actions that require it + - Features on QKSMS+ page will now link to their respective parts of the app + - Long list of names for group chat will be shortened + + Fixed + - Messages sometimes get stuck "Sending…" + - QK Reply window glitches when it\'s too big + - Crash in compose screen when a contact has no numbers + + More + Dismiss + +