diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt b/husky/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt index 81fe7f1..abe9f6d 100644 --- a/husky/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt +++ b/husky/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt @@ -1,17 +1,22 @@ -/* Copyright 2020 Tusky Contributors +/* + * Husky -- A Pleroma client for Android * - * This file is a part of Tusky. + * Copyright (C) 2021 The Husky Developers + * Copyright (C) 2020 Tusky Contributors * - * 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. + * 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. + * This program 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 . */ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package com.keylesspalace.tusky @@ -19,7 +24,6 @@ import android.app.Application import android.content.Context import android.content.res.Configuration import android.graphics.Bitmap -import android.util.Log import androidx.emoji.text.EmojiCompat import androidx.preference.PreferenceManager import androidx.work.WorkManager @@ -27,6 +31,8 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.github.piasy.biv.BigImageViewer import com.github.piasy.biv.loader.glide.GlideCustomImageLoader import com.keylesspalace.tusky.components.notifications.NotificationWorkerFactory +import com.keylesspalace.tusky.core.logging.HyperlinkDebugTree +import com.keylesspalace.tusky.core.utils.ApplicationUtils import com.keylesspalace.tusky.di.AppInjector import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.util.EmojiCompatFont @@ -36,11 +42,10 @@ import com.uber.autodispose.AutoDisposePlugins import dagger.android.DispatchingAndroidInjector import dagger.android.HasAndroidInjector import io.reactivex.plugins.RxJavaPlugins -import org.conscrypt.Conscrypt import java.security.Security import javax.inject.Inject +import org.conscrypt.Conscrypt import timber.log.Timber -import timber.log.Timber.DebugTree class TuskyApplication : Application(), HasAndroidInjector { @@ -51,18 +56,12 @@ class TuskyApplication : Application(), HasAndroidInjector { lateinit var notificationWorkerFactory: NotificationWorkerFactory override fun onCreate() { - // Uncomment me to get StrictMode violation logs -// if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { -// StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder() -// .detectDiskReads() -// .detectDiskWrites() -// .detectNetwork() -// .detectUnbufferedIo() -// .penaltyLog() -// .build()) -// } super.onCreate() + if(ApplicationUtils.isDebug()) { + Timber.plant(HyperlinkDebugTree()) + } + Security.insertProviderAt(Conscrypt.newProvider(), 1) AutoDisposePlugins.setHideProxies(false) // a small performance optimization @@ -74,8 +73,8 @@ class TuskyApplication : Application(), HasAndroidInjector { // init the custom emoji fonts val emojiSelection = preferences.getInt(PrefKeys.EMOJI, 0) val emojiConfig = EmojiCompatFont.byId(emojiSelection) - .getConfig(this) - .setReplaceAll(true) + .getConfig(this) + .setReplaceAll(true) EmojiCompat.init(emojiConfig) // init night mode @@ -83,20 +82,18 @@ class TuskyApplication : Application(), HasAndroidInjector { ThemeUtils.setAppNightMode(theme) RxJavaPlugins.setErrorHandler { - Log.w("RxJava", "undeliverable exception", it) + Timber.tag("RxJava").w("undeliverable exception: $it") } SubsamplingScaleImageView.setPreferredBitmapConfig(Bitmap.Config.ARGB_8888) BigImageViewer.initialize(GlideCustomImageLoader.with(this)) WorkManager.initialize( - this, - androidx.work.Configuration.Builder() - .setWorkerFactory(notificationWorkerFactory) - .build() + this, + androidx.work.Configuration.Builder() + .setWorkerFactory(notificationWorkerFactory) + .build() ) - - Timber.plant(DebugTree()) } override fun attachBaseContext(base: Context) { diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/core/extensions/ActivityExt.kt b/husky/app/src/main/java/com/keylesspalace/tusky/core/extensions/ActivityExt.kt new file mode 100644 index 0000000..9ec7394 --- /dev/null +++ b/husky/app/src/main/java/com/keylesspalace/tusky/core/extensions/ActivityExt.kt @@ -0,0 +1,28 @@ +/* + * Husky -- A Pleroma client for Android + * + * Copyright (C) 2021 The Husky Developers + * + * 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. + * + * This program 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 this program. If not, see . + */ + +package com.keylesspalace.tusky.core.extensions + +import android.view.LayoutInflater +import androidx.appcompat.app.AppCompatActivity +import androidx.viewbinding.ViewBinding + +inline fun AppCompatActivity.viewBinding( + crossinline bindingInflater: (LayoutInflater) -> VB +) = lazy(LazyThreadSafetyMode.NONE) { bindingInflater.invoke(layoutInflater) } diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/core/extensions/FragmentExt.kt b/husky/app/src/main/java/com/keylesspalace/tusky/core/extensions/FragmentExt.kt new file mode 100644 index 0000000..9b59cbf --- /dev/null +++ b/husky/app/src/main/java/com/keylesspalace/tusky/core/extensions/FragmentExt.kt @@ -0,0 +1,28 @@ +/* + * Husky -- A Pleroma client for Android + * + * Copyright (C) 2021 The Husky Developers + * + * 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. + * + * This program 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 this program. If not, see . + */ + +package com.keylesspalace.tusky.core.extensions + +import android.view.View +import androidx.fragment.app.Fragment +import androidx.viewbinding.ViewBinding +import com.keylesspalace.tusky.core.ui.fragment.FragmentViewBindingDelegate + +fun Fragment.viewBinding(viewBindingFactory: (View) -> VB) = + FragmentViewBindingDelegate(this, viewBindingFactory) diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/core/logging/HyperlinkDebugTree.kt b/husky/app/src/main/java/com/keylesspalace/tusky/core/logging/HyperlinkDebugTree.kt new file mode 100644 index 0000000..c64dc66 --- /dev/null +++ b/husky/app/src/main/java/com/keylesspalace/tusky/core/logging/HyperlinkDebugTree.kt @@ -0,0 +1,37 @@ +/* + * Husky -- A Pleroma client for Android + * + * Copyright (C) 2021 The Husky Developers + * + * 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. + + * This program 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 this program. If not, see . + */ + +package com.keylesspalace.tusky.core.logging + +import timber.log.Timber + +class HyperlinkDebugTree : Timber.DebugTree() { + + /** + * Override the method to put the custom log format + * + * @param [element] A StackTraceElement. + * @return A string with the custom format + */ + override fun createStackElementTag(element: StackTraceElement): String { + with(element) { + return "($fileName:$lineNumber) $methodName()" + } + } +} diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/core/ui/fragment/FragmentViewBindingDelegate.kt b/husky/app/src/main/java/com/keylesspalace/tusky/core/ui/fragment/FragmentViewBindingDelegate.kt new file mode 100644 index 0000000..9a8e22d --- /dev/null +++ b/husky/app/src/main/java/com/keylesspalace/tusky/core/ui/fragment/FragmentViewBindingDelegate.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2021 Gabor Varadi + * + * 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 com.keylesspalace.tusky.core.ui.fragment + +import android.view.View +import androidx.fragment.app.Fragment +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.Observer +import androidx.viewbinding.ViewBinding +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty + +class FragmentViewBindingDelegate( + private val fragment: Fragment, + private val viewBindingFactory: (View) -> VB +) : ReadOnlyProperty { + + private var binding: VB? = null + + init { + fragment.lifecycle.addObserver(object : DefaultLifecycleObserver { + val viewLifecycleOwnerDataObserver = Observer { + val viewLifecycleOwner = it ?: return@Observer + + viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver { + override fun onDestroy(owner: LifecycleOwner) { + binding = null + } + }) + } + + override fun onCreate(owner: LifecycleOwner) { + fragment.viewLifecycleOwnerLiveData.observeForever(viewLifecycleOwnerDataObserver) + } + + override fun onDestroy(owner: LifecycleOwner) { + fragment.viewLifecycleOwnerLiveData.removeObserver(viewLifecycleOwnerDataObserver) + } + }) + } + + override fun getValue(thisRef: Fragment, property: KProperty<*>): VB { + val binding = binding + + if(binding != null) { + return binding + } + + val lifecycleState = fragment.viewLifecycleOwner.lifecycle.currentState + if(!lifecycleState.isAtLeast(Lifecycle.State.INITIALIZED)) { + throw IllegalStateException( + "Should not attempt to get bindings when Fragment views are destroyed." + ) + } + + return viewBindingFactory(thisRef.requireView()).also { this.binding = it } + } +} diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/core/utils/ApplicationUtils.kt b/husky/app/src/main/java/com/keylesspalace/tusky/core/utils/ApplicationUtils.kt new file mode 100644 index 0000000..f8702fe --- /dev/null +++ b/husky/app/src/main/java/com/keylesspalace/tusky/core/utils/ApplicationUtils.kt @@ -0,0 +1,47 @@ +/* + * Husky -- A Pleroma client for Android + * + * Copyright (C) 2021 The Husky Developers + * + * 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. + * + * This program 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 this program. If not, see . + */ + +package com.keylesspalace.tusky.core.utils + +import com.keylesspalace.tusky.BuildConfig +import com.keylesspalace.tusky.core.utils.Flavor.DEV + +/** + * Utils for getting application details. + */ +object ApplicationUtils { + + /** + * Get if it's in DEBUG mode. + * + * @return True if DEBUG, false otherwise. + */ + fun isDebug(): Boolean { + return BuildConfig.DEBUG + } + + /** + * Get the flavor of the application. + * + * @return The flavor of the application. + */ + fun getFlavor(): Flavor { + return Flavor.getFlavor(BuildConfig.FLAVOR) + } +} diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/core/utils/DevUtils.kt b/husky/app/src/main/java/com/keylesspalace/tusky/core/utils/DevUtils.kt new file mode 100644 index 0000000..a68e3fd --- /dev/null +++ b/husky/app/src/main/java/com/keylesspalace/tusky/core/utils/DevUtils.kt @@ -0,0 +1,58 @@ +/* + * Husky -- A Pleroma client for Android + * + * Copyright (C) 2021 The Husky Developers + * + * 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. + * + * This program 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 this program. If not, see . + */ + +package com.keylesspalace.tusky.core.utils + +import android.os.Build.VERSION +import android.os.Build.VERSION_CODES +import android.os.StrictMode +import com.keylesspalace.tusky.BuildConfig +import timber.log.Timber + +object DevUtils { + + /** + * Enable StrictMode on the application. + */ + fun enableStrictMode() { + if(ApplicationUtils.isDebug()) { + val threadPolicyBuilder = + StrictMode.ThreadPolicy.Builder() + .detectDiskReads() + .detectDiskWrites() + .detectNetwork() + .penaltyLog() + + if(VERSION.SDK_INT >= VERSION_CODES.O) { + threadPolicyBuilder.detectUnbufferedIo() + } + + StrictMode.setThreadPolicy(threadPolicyBuilder.build()) + Timber.tag("StrictMode").i("setThreadPolicy") + + StrictMode.setVmPolicy( + StrictMode.VmPolicy.Builder() + .detectAll() + .penaltyLog() + .build() + ) + Timber.tag("StrictMode").i("setVmPolicy") + } + } +} diff --git a/husky/app/src/main/java/com/keylesspalace/tusky/core/utils/Flavor.kt b/husky/app/src/main/java/com/keylesspalace/tusky/core/utils/Flavor.kt new file mode 100644 index 0000000..5494dbf --- /dev/null +++ b/husky/app/src/main/java/com/keylesspalace/tusky/core/utils/Flavor.kt @@ -0,0 +1,43 @@ +/* + * Husky -- A Pleroma client for Android + * + * Copyright (C) 2021 The Husky Developers + * + * 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. + * + * This program 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 this program. If not, see . + */ + +package com.keylesspalace.tusky.core.utils + +enum class Flavor(private val flavor: String) { + + DEV("develop"), + QA("qa"), + REL("rel"); + + companion object { + + /** + * Get the flavor enum (recommended use: using Flavor. + * (: DEV, PRE, PROD). + * + * @param flavor The name of the Flavor. + */ + fun getFlavor(flavor: String) = + when(flavor) { + DEV.flavor -> DEV + QA.flavor -> QA + else -> REL + } + } +}