Skip to content
Snippets Groups Projects
Commit 8d825179 authored by John Carlson's avatar John Carlson
Browse files

Navigation and some static things to Kotlin

parent c37e8bee
No related branches found
No related tags found
No related merge requests found
Showing
with 244 additions and 292 deletions
package com.commit451.gitlab;
import android.app.Application;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.Uri;
import android.support.annotation.VisibleForTesting;
import com.bluelinelabs.logansquare.LoganSquare;
import com.commit451.gitlab.api.GitLab;
import com.commit451.gitlab.api.GitLabFactory;
import com.commit451.gitlab.api.GitLabRss;
import com.commit451.gitlab.api.GitLabRssFactory;
import com.commit451.gitlab.api.OkHttpClientFactory;
import com.commit451.gitlab.api.PicassoFactory;
import com.commit451.gitlab.api.converter.UriTypeConverter;
import com.commit451.gitlab.data.Prefs;
import com.commit451.gitlab.model.Account;
import com.commit451.gitlab.util.FabricUtil;
import com.commit451.lift.Lift;
import com.novoda.simplechromecustomtabs.SimpleChromeCustomTabs;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.picasso.Picasso;
import net.danlew.android.joda.JodaTimeAndroid;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
import java.util.Locale;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import timber.log.Timber;
/**
* App for one time init things and to house singletons
*/
public class App extends Application {
/**
* Register our type converters on our singleton LoganSquare get. Needs to be set here
* since we are fetching accounts immediately with LoganSquare
*/
static {
LoganSquare.registerTypeConverter(Uri.class, new UriTypeConverter());
}
private static EventBus bus;
private static App instance;
public static EventBus bus() {
if (bus == null) {
bus = EventBus.getDefault();
}
return bus;
}
public static App get() {
return instance;
}
private Account account;
private GitLab gitLab;
private GitLabRss gitLabRss;
private Picasso picasso;
private Prefs prefs;
@Override
public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
setupLeakCanary();
instance = this;
prefs = new Prefs(this);
//So that we don't get weird half translations
forceLocale(Locale.ENGLISH);
setupCrashReporting();
if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree());
}
JodaTimeAndroid.init(this);
SimpleChromeCustomTabs.initialize(this);
List<Account> accounts = Account.getAccounts();
if(!accounts.isEmpty()) {
setAccount(accounts.get(0));
}
Lift.check(this, new Lift.Callback() {
@Override
public void onUpgrade(int oldVersion, int newVersion) {
}
});
}
@VisibleForTesting
protected void setupCrashReporting() {
FabricUtil.init(this);
}
@VisibleForTesting
protected void setupLeakCanary() {
LeakCanary.install(this);
}
private void forceLocale(Locale locale){
try {
Locale.setDefault(locale);
Resources[] resources = new Resources[]{
Resources.getSystem(),
getBaseContext().getResources()
};
for (Resources res : resources) {
Configuration configuration = res.getConfiguration();
configuration.locale = locale;
res.updateConfiguration(configuration, res.getDisplayMetrics());
}
} catch (Exception e) {
Timber.e(e);
}
}
public GitLab getGitLab() {
return gitLab;
}
public GitLabRss getGitLabRss() {
return gitLabRss;
}
public Picasso getPicasso() {
return picasso;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
OkHttpClient.Builder clientBuilder = OkHttpClientFactory.create(account);
if (BuildConfig.DEBUG) {
clientBuilder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
}
OkHttpClient client = clientBuilder.build();
initGitLab(account, client);
initGitLabRss(account, client);
//This is kinda weird, but basically, I don't want to see all the annoying logs from bitmap
//decoding since the Okhttpclient is going to log everything, but it does not matter in release
//builds, and will actually speed up the init time to share the same client between all these
if (BuildConfig.DEBUG) {
initPicasso(OkHttpClientFactory.create(account).build());
} else {
initPicasso(client);
}
}
public Prefs getPrefs() {
return prefs;
}
private void initGitLab(Account account, OkHttpClient client) {
gitLab = GitLabFactory.create(account, client);
}
private void initGitLabRss(Account account, OkHttpClient client) {
gitLabRss = GitLabRssFactory.create(account, client);
}
private void initPicasso(OkHttpClient client) {
picasso = PicassoFactory.createPicasso(client);
}
}
package com.commit451.gitlab
import android.app.Application
import android.content.res.Resources
import android.net.Uri
import android.support.annotation.VisibleForTesting
import com.bluelinelabs.logansquare.LoganSquare
import com.commit451.gitlab.api.*
import com.commit451.gitlab.api.converter.UriTypeConverter
import com.commit451.gitlab.data.Prefs
import com.commit451.gitlab.model.Account
import com.commit451.gitlab.util.FabricUtil
import com.commit451.lift.Lift
import com.novoda.simplechromecustomtabs.SimpleChromeCustomTabs
import com.squareup.leakcanary.LeakCanary
import com.squareup.picasso.Picasso
import net.danlew.android.joda.JodaTimeAndroid
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.greenrobot.eventbus.EventBus
import timber.log.Timber
import java.util.*
/**
* App for one time init things and to house singletons
*/
open class App : Application() {
companion object {
/**
* Register our type converters on our singleton LoganSquare get. Needs to be set here
* since we are fetching accounts immediately with LoganSquare
*/
init {
LoganSquare.registerTypeConverter(Uri::class.java, UriTypeConverter())
}
var bus: EventBus = EventBus.getDefault()
lateinit private var instance: App
fun bus(): EventBus {
return bus
}
fun get(): App {
return instance
}
}
lateinit var currentAccount: Account
lateinit var gitLab: GitLab
lateinit var gitLabRss: GitLabRss
lateinit var picasso: Picasso
lateinit var prefs: Prefs
override fun onCreate() {
super.onCreate()
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return
}
setupLeakCanary()
instance = this
prefs = Prefs(this)
//So that we don't get weird half translations
forceLocale(Locale.ENGLISH)
setupCrashReporting()
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
JodaTimeAndroid.init(this)
SimpleChromeCustomTabs.initialize(this)
val accounts = Account.getAccounts()
if (!accounts.isEmpty()) {
currentAccount = accounts[0]
}
Lift.track(this)
}
fun setAccount(account: Account) {
currentAccount = account
//This is kinda weird, but basically, I don't want to see all the annoying logs from bitmap
//decoding since the Okhttpclient is going to log everything, but it does not matter in release
//builds, and will actually speed up the init time to share the same client between all these
val clientBuilder = OkHttpClientFactory.create(account)
if (BuildConfig.DEBUG) {
clientBuilder.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
}
val client = clientBuilder.build()
initGitLab(account, client)
initGitLabRss(account, client)
if (BuildConfig.DEBUG) {
initPicasso(OkHttpClientFactory.create(account).build())
} else {
initPicasso(client)
}
}
fun getAccount(): Account {
return currentAccount
}
@VisibleForTesting
protected open fun setupCrashReporting() {
FabricUtil.init(this)
}
@VisibleForTesting
protected open fun setupLeakCanary() {
LeakCanary.install(this)
}
private fun forceLocale(locale: Locale) {
try {
Locale.setDefault(locale)
val resources = arrayOf(Resources.getSystem(), baseContext.resources)
for (res in resources) {
val configuration = res.configuration
configuration.locale = locale
res.updateConfiguration(configuration, res.displayMetrics)
}
} catch (e: Exception) {
Timber.e(e)
}
}
private fun initGitLab(account: Account, client: OkHttpClient) {
gitLab = GitLabFactory.create(account, client)
}
private fun initGitLabRss(account: Account, client: OkHttpClient) {
gitLabRss = GitLabRssFactory.create(account, client)
}
private fun initPicasso(client: OkHttpClient) {
picasso = PicassoFactory.createPicasso(client)
}
}
Loading
Loading
@@ -66,7 +66,7 @@ class AboutActivity : BaseActivity() {
 
@OnClick(R.id.sauce)
fun onSauceClick() {
if (getString(R.string.url_gitlab) == App.get().account.serverUrl.toString()) {
if (getString(R.string.url_gitlab) == App.get().getAccount().serverUrl.toString()) {
Navigator.navigateToProject(this@AboutActivity, REPO_ID)
} else {
IntentUtil.openPage(this@AboutActivity, getString(R.string.source_url))
Loading
Loading
Loading
Loading
@@ -50,7 +50,7 @@ class ActivityActivity : BaseActivity() {
 
var feedFragment: FeedFragment? = supportFragmentManager.findFragmentByTag(TAG_FEED_FRAGMENT) as? FeedFragment
if (feedFragment == null) {
var feedUri = App.get().account.serverUrl
var feedUri = App.get().getAccount().serverUrl
 
feedUri = feedUri.buildUpon()
.appendPath("dashboard")
Loading
Loading
Loading
Loading
@@ -203,8 +203,8 @@ class BuildActivity : BaseActivity() {
}
 
private fun downloadBuild() {
val account = App.get().account
val downloadUrl = BuildUtil.getDownloadBuildUrl(App.get().account.serverUrl, project, build)
val account = App.get().getAccount()
val downloadUrl = BuildUtil.getDownloadBuildUrl(App.get().getAccount().serverUrl, project, build)
Timber.d("Downloading build: " + downloadUrl)
DownloadUtil.download(this@BuildActivity, account, downloadUrl, build.artifactsFile.fileName)
}
Loading
Loading
Loading
Loading
@@ -115,8 +115,8 @@ class GroupActivity : BaseActivity() {
.load(group.avatarUrl)
.transform(PaletteTransformation.instance())
.into(backdrop, object : PaletteTransformation.PaletteCallback(backdrop) {
override fun onSuccess(palette: Palette) {
bindPalette(palette)
override fun onSuccess(palette: Palette?) {
bindPalette(palette!!)
}
 
override fun onError() {}
Loading
Loading
Loading
Loading
@@ -150,7 +150,7 @@ class IssueActivity : BaseActivity() {
 
@OnClick(R.id.fab_edit_issue)
fun onEditIssueClick(fab: View) {
Navigator.navigateToEditIssue(this@IssueActivity, fab, project, issue)
Navigator.navigateToEditIssue(this@IssueActivity, fab, project!!, issue!!)
}
 
override fun onCreate(savedInstanceState: Bundle?) {
Loading
Loading
@@ -176,7 +176,7 @@ class IssueActivity : BaseActivity() {
}
 
override fun onAttachmentClicked() {
Navigator.navigateToAttach(this@IssueActivity, project, REQUEST_ATTACH)
Navigator.navigateToAttach(this@IssueActivity, project!!, REQUEST_ATTACH)
}
}
 
Loading
Loading
@@ -370,7 +370,7 @@ class IssueActivity : BaseActivity() {
override fun success(issue: Issue) {
progress.visibility = View.GONE
this@IssueActivity.issue = issue
App.bus().post(IssueChangedEvent(this@IssueActivity.issue))
App.bus().post(IssueChangedEvent(this@IssueActivity.issue!!))
App.bus().post(IssueReloadEvent())
setOpenCloseMenuStatus()
loadNotes()
Loading
Loading
Loading
Loading
@@ -139,7 +139,7 @@ class LoadSomeInfoActivity : BaseActivity() {
}
 
override fun success(repositoryCommit: RepositoryCommit) {
Navigator.navigateToDiffActivity(this@LoadSomeInfoActivity, project, repositoryCommit)
Navigator.navigateToDiffActivity(this@LoadSomeInfoActivity, project!!, repositoryCommit)
finish()
}
})
Loading
Loading
@@ -160,7 +160,7 @@ class LoadSomeInfoActivity : BaseActivity() {
 
override fun success(mergeRequests: List<MergeRequest>) {
if (!mergeRequests.isEmpty()) {
Navigator.navigateToMergeRequest(this@LoadSomeInfoActivity, project, mergeRequests[0])
Navigator.navigateToMergeRequest(this@LoadSomeInfoActivity, project!!, mergeRequests[0])
finish()
} else {
this@LoadSomeInfoActivity.onError()
Loading
Loading
@@ -183,7 +183,7 @@ class LoadSomeInfoActivity : BaseActivity() {
}
 
override fun success(build: Build) {
Navigator.navigateToBuild(this@LoadSomeInfoActivity, project, build)
Navigator.navigateToBuild(this@LoadSomeInfoActivity, project!!, build)
finish()
}
})
Loading
Loading
@@ -204,7 +204,7 @@ class LoadSomeInfoActivity : BaseActivity() {
 
override fun success(milestones: List<Milestone>) {
if (!milestones.isEmpty()) {
Navigator.navigateToMilestone(this@LoadSomeInfoActivity, project, milestones[0])
Navigator.navigateToMilestone(this@LoadSomeInfoActivity, project!!, milestones[0])
finish()
} else {
this@LoadSomeInfoActivity.onError()
Loading
Loading
Loading
Loading
@@ -361,7 +361,7 @@ class LoginActivity : BaseActivity() {
account.user = userFull
account.lastUsed = Date()
App.get().prefs.addAccount(account)
App.get().account = account
App.get().setAccount(account)
App.bus().post(LoginEvent(account))
//This is mostly for if projects already exists, then we will reload the data
App.bus().post(ReloadDataEvent())
Loading
Loading
Loading
Loading
@@ -220,7 +220,7 @@ class ProjectActivity : BaseActivity() {
}
 
fun broadcastLoad() {
App.bus().post(ProjectReloadEvent(project, ref!!.ref))
App.bus().post(ProjectReloadEvent(project!!, ref!!.ref))
}
 
fun getRefRef(): String? {
Loading
Loading
Loading
Loading
@@ -110,7 +110,7 @@ class RoutingActivity : Activity() {
 
//okay so last thing, if the user has followed a link, but the user
//is not actually signed in, we want to direct them to signin
if (App.get().account == null && Account.getAccounts().isEmpty()) {
if (App.get().getAccount() == null && Account.getAccounts().isEmpty()) {
Navigator.navigateToLogin(this)
finish()
return
Loading
Loading
Loading
Loading
@@ -68,8 +68,8 @@ class UserActivity : BaseActivity() {
.load(url)
.transform(PaletteTransformation.instance())
.into(backdrop, object : PaletteTransformation.PaletteCallback(backdrop) {
override fun onSuccess(palette: Palette) {
bindPalette(palette)
override fun onSuccess(palette: Palette?) {
bindPalette(palette!!)
}
 
override fun onError() {}
Loading
Loading
Loading
Loading
@@ -49,7 +49,7 @@ class AccountAdapter(context: Context, private val listener: AccountAdapter.List
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is AccountViewHolder) {
val account = getItemAtPosition(position)
holder.bind(account, account == App.get().account, colorControlHighlight)
holder.bind(account, account == App.get().getAccount(), colorControlHighlight)
holder.itemView.setTag(R.id.list_position, position)
holder.popupMenu.setOnMenuItemClickListener(PopupMenu.OnMenuItemClickListener { item ->
when (item.itemId) {
Loading
Loading
Loading
Loading
@@ -34,7 +34,7 @@ public final class OkHttpClientFactory {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new AuthenticationRequestInterceptor(account))
.sslSocketFactory(customTrustManager.getSSLSocketFactory(), X509TrustManagerProvider.get())
.sslSocketFactory(customTrustManager.getSSLSocketFactory(), X509TrustManagerProvider.INSTANCE.get())
.hostnameVerifier(customTrustManager.getHostnameVerifier());
 
if (includeSignInAuthenticator) {
Loading
Loading
Loading
Loading
@@ -39,12 +39,12 @@ public class OpenSignInAuthenticator implements Authenticator {
@Override
public void run() {
//Remove the account, so that the user can sign in again
App.get().getPrefs().removeAccount(account);
Toast.makeText(App.get(), R.string.error_401, Toast.LENGTH_LONG)
App.Companion.get().getPrefs().removeAccount(account);
Toast.makeText(App.Companion.get(), R.string.error_401, Toast.LENGTH_LONG)
.show();
Intent intent = LoginActivity.Companion.newIntent(App.get());
Intent intent = LoginActivity.Companion.newIntent(App.Companion.get());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
App.get().startActivity(intent);
App.Companion.get().startActivity(intent);
}
});
}
Loading
Loading
package com.commit451.gitlab.api;
import com.commit451.gitlab.App;
import com.jakewharton.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;
import okhttp3.OkHttpClient;
/**
* Creates {@link com.squareup.picasso.Picasso} instances based on the account logged in to
*/
public class PicassoFactory {
public static Picasso createPicasso(OkHttpClient client) {
return new Picasso.Builder(App.get())
.downloader(new OkHttp3Downloader(client))
.build();
}
}
package com.commit451.gitlab.api
import com.commit451.gitlab.App
import com.jakewharton.picasso.OkHttp3Downloader
import com.squareup.picasso.Picasso
import okhttp3.OkHttpClient
/**
* Creates [com.squareup.picasso.Picasso] instances based on the account logged in to
*/
object PicassoFactory {
fun createPicasso(client: OkHttpClient): Picasso {
return Picasso.Builder(App.get())
.downloader(OkHttp3Downloader(client))
.build()
}
}
package com.commit451.gitlab.api;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
/**
* Gets the X509TrustManager on the system and caches it
*/
public class X509TrustManagerProvider {
private static X509TrustManager x509TrustManager;
/**
* Get the static {@link X509TrustManager} for the system
*
* @return the static get
*/
public static X509TrustManager get() {
if (x509TrustManager == null) {
try {
init();
} catch (Exception any) {
//If they don't have X509 trust manager, they have bigger problems
throw new RuntimeException(any);
}
}
return x509TrustManager;
}
/**
* Getting the {@link X509TrustManager} as shown in the {@link okhttp3.OkHttpClient.Builder#sslSocketFactory(SSLSocketFactory, X509TrustManager)} docs
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
*/
private static void init() throws NoSuchAlgorithmException, KeyStoreException {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
x509TrustManager = (X509TrustManager) trustManagers[0];
}
}
package com.commit451.gitlab.api
import java.security.KeyStore
import java.security.KeyStoreException
import java.security.NoSuchAlgorithmException
import java.util.Arrays
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
/**
* Gets the X509TrustManager on the system and caches it
*/
object X509TrustManagerProvider {
private var x509TrustManager: X509TrustManager? = null
/**
* Get the static [X509TrustManager] for the system
* @return the static get
*/
fun get(): X509TrustManager {
if (x509TrustManager == null) {
try {
init()
} catch (any: Exception) {
//If they don't have X509 trust manager, they have bigger problems
throw RuntimeException(any)
}
}
return x509TrustManager
}
/**
* Getting the [X509TrustManager] as shown in the [okhttp3.OkHttpClient.Builder.sslSocketFactory] docs
* @throws NoSuchAlgorithmException
* *
* @throws KeyStoreException
*/
@Throws(NoSuchAlgorithmException::class, KeyStoreException::class)
private fun init() {
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(null as KeyStore)
val trustManagers = trustManagerFactory.trustManagers
if (trustManagers.size != 1 || trustManagers[0] !is X509TrustManager) {
throw IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers))
}
x509TrustManager = trustManagers[0] as X509TrustManager
}
}
package com.commit451.gitlab.event;
import com.commit451.gitlab.model.api.Build;
/**
* A build changed
*/
public class BuildChangedEvent {
public final Build build;
public BuildChangedEvent(Build build) {
this.build = build;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment