diff --git a/app/build.gradle b/app/build.gradle index f7f1dc4d1..0810eab9f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -96,6 +96,12 @@ project.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { ext.daggerVersion = '2.24' ext.retrofitVersion = '2.6.0' +repositories { + maven { + url 'https://maven.accelf.net/' + } +} + // if libraries are changed here, they should also be changed in LicenseActivity dependencies { implementation('com.mikepenz:materialdrawer:6.1.2@aar') { @@ -165,4 +171,6 @@ dependencies { //Add some useful extensions implementation 'androidx.core:core-ktx:1.2.0-alpha01' + + implementation 'net.accelf:easter:1.0.1' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 16bbd3bae..bee9f4d6f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -173,6 +173,8 @@ android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> + + \ No newline at end of file diff --git a/app/src/main/java/com/keylesspalace/tusky/AboutActivity.kt b/app/src/main/java/com/keylesspalace/tusky/AboutActivity.kt index c05bd9f48..7cff76f70 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AboutActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/AboutActivity.kt @@ -14,6 +14,7 @@ import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.util.CustomURLSpan import kotlinx.android.synthetic.main.activity_about.* import kotlinx.android.synthetic.main.toolbar_basic.* +import net.accelf.yuito.AccessTokenLoginActivity class AboutActivity : BottomSheetActivity(), Injectable { @@ -29,6 +30,10 @@ class AboutActivity : BottomSheetActivity(), Injectable { setTitle(R.string.about_title_activity) + easterView.setOnEasterEggExecuteListener { + onEasterEggExecute() + } + versionTextView.text = getString(R.string.about_tusky_version, BuildConfig.VERSION_NAME) aboutLicenseInfoTextView.setClickableTextWithoutUnderlines(R.string.about_tusky_license) @@ -46,6 +51,10 @@ class AboutActivity : BottomSheetActivity(), Injectable { } + private fun onEasterEggExecute() { + startActivityWithSlideInAnimation(Intent(this, AccessTokenLoginActivity::class.java)) + } + private fun onAccountButtonClick() { viewUrl("https://mastodon.social/@Tusky", getString(R.string.about_tusky_account)) } diff --git a/app/src/main/java/com/keylesspalace/tusky/LicenseActivity.kt b/app/src/main/java/com/keylesspalace/tusky/LicenseActivity.kt index 915baf963..19f66e85b 100644 --- a/app/src/main/java/com/keylesspalace/tusky/LicenseActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/LicenseActivity.kt @@ -45,6 +45,7 @@ class LicenseActivity : BaseActivity() { setTitle(R.string.title_licenses) loadFileIntoTextView(R.raw.apache, licenseApacheTextView) + loadFileIntoTextView(R.raw.mit, licenseMitTextView) } diff --git a/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt index ed4151b22..060845dc8 100644 --- a/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt +++ b/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt @@ -21,6 +21,7 @@ import com.keylesspalace.tusky.components.report.ReportActivity import com.keylesspalace.tusky.components.search.SearchActivity import dagger.Module import dagger.android.ContributesAndroidInjector +import net.accelf.yuito.AccessTokenLoginActivity /** * Created by charlag on 3/24/18. @@ -97,4 +98,7 @@ abstract class ActivitiesModule { @ContributesAndroidInjector(modules = [FragmentBuildersModule::class]) abstract fun contributesInstanceListActivity(): InstanceListActivity + + @ContributesAndroidInjector + abstract fun contributesAccessTokenLoginActivity(): AccessTokenLoginActivity } diff --git a/app/src/main/java/net/accelf/yuito/AccessTokenLoginActivity.java b/app/src/main/java/net/accelf/yuito/AccessTokenLoginActivity.java new file mode 100644 index 000000000..9b8b44404 --- /dev/null +++ b/app/src/main/java/net/accelf/yuito/AccessTokenLoginActivity.java @@ -0,0 +1,110 @@ +package net.accelf.yuito; + +import android.content.Intent; +import android.os.Bundle; +import android.widget.Button; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; + +import com.google.android.material.textfield.TextInputEditText; +import com.keylesspalace.tusky.MainActivity; +import com.keylesspalace.tusky.R; +import com.keylesspalace.tusky.db.AccountManager; +import com.keylesspalace.tusky.di.Injectable; + +import java.io.IOException; + +import javax.inject.Inject; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +public class AccessTokenLoginActivity extends AppCompatActivity implements Injectable { + + @Inject + AccountManager accountManager; + + TextInputEditText domainEditText; + TextInputEditText accessTokenEditText; + TextView logTextView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_access_token_login); + + domainEditText = findViewById(R.id.domainEditText); + accessTokenEditText = findViewById(R.id.accessTokenEditText); + Button authorizeButton = findViewById(R.id.authorizeButton); + logTextView = findViewById(R.id.logTextView); + + authorizeButton.setOnClickListener(v -> authorize()); + log("Input domain and access token to login."); + } + + private void log(String text) { + runOnUiThread(() -> logTextView.setText(String.format("%s\n%s", logTextView.getText().toString(), text))); + } + + private void authorize() { + if (domainEditText.getText() != null) { + String domain = domainEditText.getText().toString(); + String accessToken = accessTokenEditText.getText().toString(); + HttpUrl url; + + log("Starting login test. [domain: " + domain + ", accessToken: " + accessToken + "]"); + + try { + url = new HttpUrl.Builder().host(domain).scheme("https") + .addPathSegments("/api/v1/accounts/verify_credentials") + .addQueryParameter("access_token", accessToken) + .build(); + } catch (IllegalArgumentException e) { + log("Wrong domain format. " + e.getMessage()); + log("Aborting."); + return; + } + + log("Access start -> " + url.toString()); + + OkHttpClient okHttpClient = new OkHttpClient(); + Request request = new Request.Builder().url(url).get().build(); + okHttpClient.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + log("Login failed. " + e.getMessage()); + log("Aborting."); + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { + if (response.body() != null) { + log(response.body().string()); + } + if (response.code() != 200) { + throw new IOException("Invalid response code. Response code was " + response.code()); + } + log("Login successful. Moving to account registration phase."); + authSucceeded(domain, accessToken); + } + }); + } + } + + private void authSucceeded(String domain, String accessToken) { + accountManager.addAccount(accessToken, domain); + log("Completed. Enjoy!"); + + Intent intent = new Intent(this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + finish(); + overridePendingTransition(R.anim.explode, R.anim.explode); + } +} diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 8a6c5cf21..51c889acf 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -41,6 +41,11 @@ android:textSize="24sp" android:textStyle="bold" /> + + + + + + + + +