Commit bc67eb6d authored by Thomas Markiewicz's avatar Thomas Markiewicz
Browse files

Merged upstream version 6.1

parents c148c040 fb2d3024
Pipeline #9089 canceled with stage
version: 2
machine:
environment:
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"'
jobs:
test:
working_directory: ~/code
docker:
- image: circleci/android:api-27-alpha
environment:
JVM_OPTS: -Xmx3200m
steps:
- checkout
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
# - run:
# name: Chmod permissions #if permission for Gradlew Dependencies fail, use this.
# command: sudo chmod +x ./gradlew
- run:
name: Download Dependencies
command: ./gradlew androidDependencies
- save_cache:
paths:
- ~/.gradle
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:
name: Run Tests
command: ./gradlew --no-daemon test
- store_artifacts:
path: app/build/reports
destination: reports
- store_test_results:
path: app/build/test-results
build:
working_directory: ~/code
docker:
- image: circleci/android:api-27-alpha
environment:
JVM_OPTS: -Xmx3200m
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx3200m -XX:+HeapDumpOnOutOfMemoryError"'
steps:
- checkout
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:
name: Build apk
command: |
./gradlew assembleBlueRelease --no-daemon --stacktrace
/opt/android/sdk/build-tools/27.0.3/zipalign -v -p 4 app/build/outputs/apk/blue/release/app-blue-release-unsigned.apk app-blue-release-aligned.apk
keytool -genkey -v -keystore debug.keystore -alias androiddebugkey -storepass android -keypass android -keyalg RSA -dname "C=US, O=Android, CN=Android Debug"
/opt/android/sdk/build-tools/27.0.3/apksigner sign --ks debug.keystore --out app-blue-release.apk --ks-pass pass:android app-blue-release-aligned.apk
- store_artifacts:
path: app-blue-release.apk
destination: app-blue-release.apk
workflows:
version: 2
test-and-build:
jobs:
- test
- build:
requires:
- test
CHANGES
=======
Version 0.1.0 released to Play Store on 2019-04-10
-------------------------------------------------
Version 0.1.1 released to Google Play Store on April ??, 2019
-------------------------------------------------------------
* Merged upstream version 6.1
Version 0.1.0 released to Google Play Store on April 10, 2019
-------------------------------------------------------------
* Initial release
[![Translate - with Stringlate](https://img.shields.io/badge/translate%20with-stringlate-green.svg)](https://lonamiwebs.github.io/stringlate/translate?git=https%3A%2F%2Fgithub.com%2Ftuskyapp%2FTusky) [![Build Status](https://app.bitrise.io/app/a3e773c3c57a894c/status.svg?token=qLu_Ti4Gp2LWcYT4eo2INQ&branch=master)](https://app.bitrise.io/app/a3e773c3c57a894c#/builds)
[![Translate - with Weblate](https://img.shields.io/badge/translate%20with-Weblate-green.svg?style=flat)](https://weblate.tusky.app/) [![OpenCollective](https://opencollective.com/tusky/backers/badge.svg)](https://opencollective.com/tusky/) [![Build Status](https://app.bitrise.io/app/a3e773c3c57a894c/status.svg?token=qLu_Ti4Gp2LWcYT4eo2INQ&branch=master)](https://app.bitrise.io/app/a3e773c3c57a894c#/builds)
# Tusky
![](/fastlane/metadata/android/en-US/images/icon.png)
......@@ -35,3 +35,5 @@ The current maintainer is [ConnyDuck@chaos.social](https://chaos.social/@ConnyDu
### Development chatroom
https://riot.im/app/#/room/#Tusky:matrix.org
###
......@@ -18,8 +18,8 @@ android {
applicationId "com.keylesspalace.tusky"
minSdkVersion 21
targetSdkVersion 28
versionCode 52
versionName "4.1"
versionCode 59
versionName "6.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
......@@ -86,30 +86,36 @@ android {
exclude 'LICENSE_OFL'
exclude 'LICENSE_UNICODE'
}
bundle {
language {
// bundle all languages in every apk so the dynamic language switching works
enableSplit = false
}
}
}
ext.daggerVersion = '2.19'
ext.daggerVersion = '2.22.1'
// if libraries are changed here, they should also be changed in LicenseActivity
dependencies {
implementation('com.mikepenz:materialdrawer:6.1.1@aar') {
transitive = true
}
implementation 'androidx.core:core:1.0.1'
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.browser:browser:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
implementation 'com.google.android.material:material:1.1.0-alpha02'
implementation 'com.google.android.material:material:1.1.0-alpha05'
implementation 'androidx.exifinterface:exifinterface:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.preference:preference:1.1.0-alpha02'
implementation 'androidx.preference:preference:1.1.0-alpha04'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.12.0'
implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
implementation 'com.squareup.okhttp3:okhttp:3.14.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.14.0'
implementation 'org.conscrypt:conscrypt-android:2.1.0'
implementation 'com.github.connyduck:sparkbutton:2.0.0'
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
implementation 'com.mikepenz:google-material-typeface:3.0.1.3.original@aar'
......@@ -127,27 +133,32 @@ dependencies {
//room
implementation 'androidx.room:room-runtime:2.0.0'
kapt 'androidx.room:room-compiler:2.0.0'
implementation 'android.arch.persistence.room:rxjava2:1.1.1'
implementation 'androidx.room:room-rxjava2:2.0.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
implementation "com.google.dagger:dagger:$daggerVersion"
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
implementation "com.google.dagger:dagger-android:$daggerVersion"
implementation "com.google.dagger:dagger-android-support:$daggerVersion"
kapt "com.google.dagger:dagger-android-processor:$daggerVersion"
testImplementation 'org.robolectric:robolectric:4.1'
testImplementation 'org.mockito:mockito-inline:2.23.4'
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0"
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', {
testImplementation 'org.robolectric:robolectric:4.2.1'
testImplementation 'org.mockito:mockito-inline:2.26.0'
testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0'
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.1', {
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestImplementation('android.arch.persistence.room:testing:1.1.1')
androidTestImplementation "androidx.test.ext:junit:1.1.0"
androidTestImplementation 'android.arch.persistence.room:testing:1.1.1'
testImplementation 'androidx.test.ext:junit:1.1.0'
debugImplementation 'im.dino:dbinspector:3.4.1@aar'
implementation 'io.reactivex.rxjava2:rxjava:2.2.4'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
implementation 'com.uber.autodispose:autodispose-android-archcomponents:1.1.0'
implementation 'com.uber.autodispose:autodispose-ktx:1.1.0'
implementation 'com.uber.autodispose:autodispose-android-archcomponents:1.2.0'
implementation 'com.uber.autodispose:autodispose-ktx:1.2.0'
implementation 'androidx.paging:paging-runtime-ktx:2.1.0'
//Glide
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
implementation 'com.github.bumptech.glide:okhttp3-integration:4.9.0'
}
......@@ -49,9 +49,6 @@
-dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn okhttp3.internal.platform.ConscryptPlatform
## for picasso
-dontwarn com.squareup.okhttp.**
##for keep
-dontwarn android.arch.util.paging.CountedDataSource
-dontwarn android.arch.persistence.room.paging.LimitOffsetDataSource
......@@ -100,3 +97,11 @@
# work around a bug in proguard
# see https://sourceforge.net/p/proguard/bugs/729/
-keepnames public interface com.uber.autodispose.lifecycle.CorrespondingEventsFunction { *; }
# Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -10,7 +10,7 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
const val TEST_DB = "mirgation_test"
const val TEST_DB = "migration_test"
@RunWith(AndroidJUnit4::class)
class MigrationsTest {
......
......@@ -133,7 +133,6 @@ class TimelineDAOTest {
val author = TimelineAccountEntity(
authorServerId,
accountId,
"birb.site",
"localUsername",
"username",
"displayName",
......@@ -146,7 +145,6 @@ class TimelineDAOTest {
TimelineAccountEntity(
"R$authorServerId",
accountId,
"Rbirb.site",
"RlocalUsername",
"Rusername",
"RdisplayName",
......@@ -163,7 +161,6 @@ class TimelineDAOTest {
url = "url$statusId",
timelineUserId = accountId,
authorServerId = authorServerId,
instance = "birb.site$statusId",
inReplyToId = "inReplyToId$statusId",
inReplyToAccountId = "inReplyToAccountId$statusId",
content = "Content!$statusId",
......@@ -185,13 +182,12 @@ class TimelineDAOTest {
return Triple(status, author, reblogAuthor)
}
fun createPlaceholder(serverId: String, timelineUserId: Long): TimelineStatusEntity {
private fun createPlaceholder(serverId: String, timelineUserId: Long): TimelineStatusEntity {
return TimelineStatusEntity(
serverId = serverId,
url = null,
timelineUserId = timelineUserId,
authorServerId = null,
instance = null,
inReplyToId = null,
inReplyToAccountId = null,
content = null,
......
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:icon="@mipmap/ic_shortcut_compose"
android:shortcutId="com.keylesspalace.tusky.Compose"
android:shortcutLongLabel="@string/compose_shortcut_long_label"
android:shortcutShortLabel="@string/compose_shortcut_short_label">
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.keylesspalace.tusky.SplashActivity"
android:targetPackage="com.keylesspalace.tusky"/>
<intent
android:action="com.keylesspalace.tusky.Compose"
android:targetClass="com.keylesspalace.tusky.ComposeActivity"
android:targetPackage="com.keylesspalace.tusky"/>
</shortcut>
</shortcuts>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:icon="@mipmap/ic_shortcut_compose"
android:shortcutId="com.keylesspalace.tusky.Compose"
android:shortcutLongLabel="@string/compose_shortcut_long_label"
android:shortcutShortLabel="@string/compose_shortcut_short_label">
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.keylesspalace.tusky.SplashActivity"
android:targetPackage="com.keylesspalace.tusky.test"/>
<intent
android:action="com.keylesspalace.tusky.Compose"
android:targetClass="com.keylesspalace.tusky.ComposeActivity"
android:targetPackage="com.keylesspalace.tusky.test"/>
</shortcut>
</shortcuts>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:icon="@mipmap/ic_shortcut_compose"
android:shortcutId="com.keylesspalace.tusky.Compose"
android:shortcutLongLabel="@string/compose_shortcut_long_label"
android:shortcutShortLabel="@string/compose_shortcut_short_label">
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.keylesspalace.tusky.SplashActivity"
android:targetPackage="com.keylesspalace.tusky"/>
<intent
android:action="com.keylesspalace.tusky.Compose"
android:targetClass="com.keylesspalace.tusky.ComposeActivity"
android:targetPackage="com.keylesspalace.tusky"/>
</shortcut>
</shortcuts>
\ No newline at end of file
......@@ -26,6 +26,9 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts"/>
</activity>
<activity
android:name=".SavedTootActivity"
......@@ -97,6 +100,7 @@
<activity android:name=".FavouritesActivity" />
<activity android:name=".AccountListActivity" />
<activity android:name=".AboutActivity" />
<activity android:name=".TabPreferenceActivity" />
<activity
android:name=".ReportActivity"
android:windowSoftInputMode="stateVisible|adjustResize" />
......@@ -114,6 +118,7 @@
<activity android:name=".ListsActivity" />
<activity android:name=".ModalTimelineActivity" />
<activity android:name=".LicenseActivity" />
<activity android:name=".FiltersActivity" />
<receiver android:name=".receiver.NotificationClearBroadcastReceiver" />
......
......@@ -37,20 +37,22 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.CollapsingToolbarLayout
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
import com.keylesspalace.tusky.adapter.AccountFieldAdapter
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.entity.Relationship
import com.keylesspalace.tusky.interfaces.ActionButtonActivity
import com.keylesspalace.tusky.interfaces.LinkListener
import com.keylesspalace.tusky.interfaces.ReselectableFragment
import com.keylesspalace.tusky.pager.AccountPagerAdapter
import com.keylesspalace.tusky.util.*
import com.keylesspalace.tusky.viewmodel.AccountViewModel
import com.squareup.picasso.Picasso
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector
......@@ -104,6 +106,8 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
REQUESTED
}
private var adapter: AccountPagerAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
......@@ -174,7 +178,8 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
// Add a listener to change the toolbar icon color when it enters/exits its collapsed state.
accountAppBarLayout.addOnOffsetChangedListener(object : AppBarLayout.OnOffsetChangedListener {
@AttrRes var priorAttribute = R.attr.account_toolbar_icon_tint_uncollapsed
@AttrRes
var priorAttribute = R.attr.account_toolbar_icon_tint_uncollapsed
override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
......@@ -250,9 +255,9 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
accountFieldList.adapter = accountFieldAdapter
// Setup the tabs and timeline pager.
val adapter = AccountPagerAdapter(supportFragmentManager, accountId)
adapter = AccountPagerAdapter(supportFragmentManager, accountId)
val pageTitles = arrayOf(getString(R.string.title_statuses), getString(R.string.title_statuses_with_replies), getString(R.string.title_statuses_pinned), getString(R.string.title_media))
adapter.setPageTitles(pageTitles)
adapter?.setPageTitles(pageTitles)
accountFragmentViewPager.pageMargin = resources.getDimensionPixelSize(R.dimen.tab_page_margin)
val pageMarginDrawable = ThemeUtils.getDrawable(this, R.attr.tab_page_margin_drawable,
R.drawable.tab_page_margin_dark)
......@@ -260,10 +265,21 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
accountFragmentViewPager.adapter = adapter
accountFragmentViewPager.offscreenPageLimit = 2
accountTabLayout.setupWithViewPager(accountFragmentViewPager)
accountTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabReselected(tab: TabLayout.Tab?) {
tab?.position?.let {
(adapter?.getFragment(tab.position) as? ReselectableFragment)?.onReselect()
}
}
override fun onTabUnselected(tab: TabLayout.Tab?) {}
override fun onTabSelected(tab: TabLayout.Tab?) {}
})
val accountListClickListener = { v: View ->
val type = when (v.id) {
R.id.accountFollowers-> AccountListActivity.Type.FOLLOWERS
R.id.accountFollowers -> AccountListActivity.Type.FOLLOWERS
R.id.accountFollowing -> AccountListActivity.Type.FOLLOWS
else -> throw AssertionError()
}
......@@ -300,18 +316,17 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
supportActionBar?.subtitle = subtitle
}
val emojifiedNote = CustomEmojiHelper.emojifyText(account.note, account.emojis, accountNoteTextView)
setClickableText(accountNoteTextView, emojifiedNote, null, this)
LinkHelper.setClickableText(accountNoteTextView, emojifiedNote, null, this)
accountLockedImageView.visible(account.locked)
accountBadgeTextView.visible(account.bot)
Picasso.with(this)
Glide.with(this)
.load(account.avatar)
.placeholder(R.drawable.avatar_default)
.into(accountAvatarImageView)
Picasso.with(this)
Glide.with(this)
.load(account.header)
.fit() // prevents crash with large header images
.centerCrop()
.into(accountHeaderImageView)
......@@ -341,7 +356,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
accountMovedDisplayName.text = movedAccount.name
accountMovedUsername.text = getString(R.string.status_username_format, movedAccount.username)
Picasso.with(this)
Glide.with(this)
.load(movedAccount.avatar)
.placeholder(R.drawable.avatar_default)
.into(accountMovedAvatar)
......@@ -365,7 +380,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
if (account.isRemote()) {
accountRemoveView.show()
accountRemoveView.setOnClickListener {
openLink(account.url, this)
LinkHelper.openLink(account.url, this)
}
}
......@@ -424,7 +439,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
}
private fun updateFollowButton() {
if(isSelf) {
if (isSelf) {
accountFollowButton.setText(R.string.action_edit_own_profile)
return
}
......@@ -449,7 +464,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
accountFollowButton.show()
updateFollowButton()
if(isSelf) {
if (isSelf) {
accountFloatingActionButton.hide()
} else {
accountFloatingActionButton.show()
......@@ -463,10 +478,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.account_toolbar, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
if (!isSelf) {
val follow = menu.findItem(R.id.action_follow)
follow.title = if (followState == FollowState.NOT_FOLLOWING) {
......@@ -510,7 +522,8 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
menu.removeItem(R.id.action_mute)
menu.removeItem(R.id.action_show_reblogs)
}
return super.onPrepareOptionsMenu(menu)
return super.onCreateOptionsMenu(menu)
}
private fun showFollowRequestPendingDialog() {
......@@ -567,7 +580,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF
R.id.action_open_in_web -> {
// If the account isn't loaded yet, eat the input.
if (loadedAccount != null) {
openLink(loadedAccount?.url, this)
LinkHelper.openLink(loadedAccount?.url, this)
}
return true
}
......
/* Copyright 2017 Andrew Dawson
*
* This file is a part of Tusky.
*
* This program 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.
*
* Tusky 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 Tusky; if not,
* see <http://www.gnu.org/licenses>.
*/
package com.keylesspalace.tusky
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.util.Either
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.viewmodel.AccountsInListViewModel
import com.keylesspalace.tusky.viewmodel.State
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider.from