Handle attachments in issue, pr and comments (#1304)

Closes #56

Closes #1313

Closes #1215

Closes #926

Closes #1315

Closes #1321

Closes #1322

Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1304
Co-authored-by: M M Arif <mmarif@swatian.com>
Co-committed-by: M M Arif <mmarif@swatian.com>
This commit is contained in:
M M Arif 2024-02-11 13:20:23 +00:00 committed by M M Arif
parent a3fa2344a4
commit 72a2b82558
94 changed files with 5422 additions and 4575 deletions

View File

@ -84,7 +84,7 @@ Thanks to all the open source libraries, contributors, and donors.
- [ocpsoft/prettytime](https://github.com/ocpsoft/prettytime)
- [ramseth001/TextDrawable](https://github.com/ramseth001/TextDrawable)
- [vdurmont/emoji-java](https://github.com/vdurmont/emoji-java)
- [Pes8/android-material-color-picker-dialog](https://github.com/Pes8/android-material-color-picker-dialog)
- [skydoves/ColorPickerView](https://github.com/skydoves/ColorPickerView)
- [HamidrezaAmz/BreadcrumbsView](https://github.com/HamidrezaAmz/BreadcrumbsView)
- [Baseflow/PhotoView](https://github.com/Baseflow/PhotoView)
- [apache/commons](https://github.com/apache/commons-io)

View File

@ -4,7 +4,6 @@ plugins {
apply plugin: 'com.android.application'
android {
compileSdkVersion 34
defaultConfig {
applicationId "org.mian.gitnex"
minSdkVersion 23
@ -13,8 +12,9 @@ android {
versionName "5.3.0-dev"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
compileSdk 34
}
flavorDimensions "default"
flavorDimensions = ["default"]
productFlavors {
free {
applicationId "org.mian.gitnex"
@ -57,13 +57,13 @@ dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0-alpha03'
implementation 'androidx.compose.material3:material3:1.2.0-alpha08'
implementation 'androidx.compose.material3:material3-window-size-class:1.2.0-alpha08'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.compose.material3:material3:1.2.0-beta02'
implementation 'androidx.compose.material3:material3-window-size-class:1.2.0-beta02'
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta02'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:2.6.2"
implementation "androidx.lifecycle:lifecycle-viewmodel:2.7.0"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
@ -76,7 +76,7 @@ dependencies {
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'
implementation 'org.ocpsoft.prettytime:prettytime:5.0.7.Final'
implementation 'com.github.Pes8:android-material-color-picker-dialog:master'
implementation "com.github.skydoves:colorpickerview:2.3.0"
implementation "io.noties.markwon:core:4.6.2"
implementation "io.noties.markwon:ext-latex:4.6.2"
implementation "io.noties.markwon:ext-strikethrough:4.6.2"
@ -99,18 +99,18 @@ dependencies {
implementation 'ch.acra:acra-mail:5.11.2'
implementation 'ch.acra:acra-limiter:5.11.2'
implementation 'ch.acra:acra-notification:5.11.2'
implementation 'androidx.room:room-runtime:2.5.2'
annotationProcessor 'androidx.room:room-compiler:2.5.2'
implementation "androidx.work:work-runtime:2.8.1"
implementation 'androidx.room:room-runtime:2.6.1'
annotationProcessor 'androidx.room:room-compiler:2.6.1'
implementation "androidx.work:work-runtime:2.9.0"
implementation "io.mikael:urlbuilder:2.0.9"
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
//noinspection GradleDependency
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
implementation 'androidx.biometric:biometric:1.1.0'
implementation 'com.github.chrisvest:stormpot:2.4.2'
implementation 'androidx.browser:browser:1.6.0'
implementation 'androidx.browser:browser:1.7.0'
implementation 'com.google.android.flexbox:flexbox:3.0.0'
implementation('org.codeberg.gitnex:tea4j-autodeploy:65f700d036') {
implementation('org.codeberg.gitnex:tea4j-autodeploy:4646f53557') {
exclude module: 'org.apache.oltu.oauth2.common'
}
implementation 'io.github.amrdeveloper:codeview:1.3.8'

View File

@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
<application
android:name=".core.MainApplication"
@ -47,13 +48,16 @@
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
<activity
android:name=".activities.EditIssueActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".activities.CreateNewUserActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".activities.AccountSettingsEmailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".activities.AddCollaboratorToRepositoryActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
@ -69,13 +73,16 @@
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".activities.CreateLabelActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".activities.CreateIssueActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".activities.CreateMilestoneActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".activities.IssueDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
@ -101,10 +108,12 @@
android:theme="@android:style/Theme.NoTitleBar"/>
<activity
android:name=".activities.CreateRepoActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".activities.CreateOrganizationActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".activities.DiffActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
@ -139,13 +148,15 @@
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
<activity
android:name=".activities.AddNewAccountActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".activities.RepositorySettingsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
<activity
android:name=".activities.CreatePullRequestActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".activities.SettingsGeneralActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"/>
@ -165,7 +176,7 @@
<activity
android:name=".activities.CreateNoteActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustResize" />
android:windowSoftInputMode="adjustResize"/>
<meta-data
android:name="com.samsung.android.keepalive.density"

View File

@ -1,11 +1,8 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.os.Handler;
import android.util.Patterns;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.Arrays;
@ -18,8 +15,7 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityAccountSettingsEmailBinding;
import org.mian.gitnex.fragments.AccountSettingsEmailsFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import retrofit2.Call;
import retrofit2.Callback;
@ -28,8 +24,6 @@ import retrofit2.Callback;
*/
public class AccountSettingsEmailActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private final View.OnClickListener addEmailListener = v -> processAddNewEmail();
private ActivityAccountSettingsEmailBinding activityAccountSettingsEmailBinding;
@Override
@ -41,56 +35,42 @@ public class AccountSettingsEmailActivity extends BaseActivity {
ActivityAccountSettingsEmailBinding.inflate(getLayoutInflater());
setContentView(activityAccountSettingsEmailBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
activityAccountSettingsEmailBinding.topAppBar.setNavigationOnClickListener(v -> finish());
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
activityAccountSettingsEmailBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
activityAccountSettingsEmailBinding.userEmail.requestFocus();
assert imm != null;
imm.showSoftInput(
activityAccountSettingsEmailBinding.userEmail, InputMethodManager.SHOW_IMPLICIT);
initCloseListener();
activityAccountSettingsEmailBinding.close.setOnClickListener(onClickListener);
if (!connToInternet) {
disableProcessButton();
} else {
activityAccountSettingsEmailBinding.addEmailButton.setOnClickListener(addEmailListener);
}
if (id == R.id.save) {
processAddNewEmail();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
}
private void processAddNewEmail() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newUserEmail =
Objects.requireNonNull(activityAccountSettingsEmailBinding.userEmail.getText())
.toString()
.trim();
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (newUserEmail.equals("")) {
Toasty.error(ctx, getString(R.string.emailErrorEmpty));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.emailErrorEmpty));
return;
} else if (!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) {
Toasty.warning(ctx, getString(R.string.emailErrorInvalid));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.emailErrorInvalid));
return;
}
List<String> newEmailList = new ArrayList<>(Arrays.asList(newUserEmail.split(",")));
disableProcessButton();
addNewEmail(newEmailList);
}
@ -111,54 +91,44 @@ public class AccountSettingsEmailActivity extends BaseActivity {
if (response.code() == 201) {
Toasty.success(ctx, getString(R.string.emailAddedText));
SnackBar.info(
ctx,
findViewById(android.R.id.content),
getString(R.string.emailAddedText));
AccountSettingsEmailsFragment.refreshEmails = true;
enableProcessButton();
finish();
new Handler().postDelayed(() -> finish(), 3000);
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else if (response.code() == 403) {
enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.authorizeError));
} else if (response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.apiNotFound));
} else if (response.code() == 422) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.emailErrorInUse));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.emailErrorInUse));
} else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<List<Email>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
public void onFailure(@NonNull Call<List<Email>> call, @NonNull Throwable t) {}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
activityAccountSettingsEmailBinding.addEmailButton.setEnabled(false);
}
private void enableProcessButton() {
activityAccountSettingsEmailBinding.addEmailButton.setEnabled(true);
}
}

View File

@ -3,8 +3,7 @@ package org.mian.gitnex.activities;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.os.Handler;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
@ -22,7 +21,7 @@ import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.databinding.ActivityAddNewAccountBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.structs.Protocol;
@ -34,7 +33,6 @@ import retrofit2.Callback;
*/
public class AddNewAccountActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private ActivityAddNewAccountBinding viewBinding;
private String spinnerSelectedValue;
@ -52,8 +50,6 @@ public class AddNewAccountActivity extends BaseActivity {
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
viewBinding.instanceUrl.setText(getIntent().getStringExtra("instanceUrl"));
viewBinding.loginToken.setText(getIntent().getStringExtra("token"));
String scheme = getIntent().getStringExtra("scheme");
@ -68,20 +64,22 @@ public class AddNewAccountActivity extends BaseActivity {
ArrayAdapter<Protocol> adapterProtocols =
new ArrayAdapter<>(ctx, R.layout.list_spinner_items, Protocol.values());
viewBinding.topAppBar.setNavigationOnClickListener(v -> finish());
viewBinding.protocolSpinner.setAdapter(adapterProtocols);
viewBinding.protocolSpinner.setOnItemClickListener(
(parent, view1, position, id) ->
spinnerSelectedValue = String.valueOf(parent.getItemAtPosition(position)));
viewBinding.addNewAccount.setOnClickListener(
login -> {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
} else {
viewBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
if (id == R.id.addAccount) {
processLogin();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
}
@ -102,19 +100,26 @@ public class AddNewAccountActivity extends BaseActivity {
if (protocol == null) {
Toasty.error(ctx, getResources().getString(R.string.protocolEmptyError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.protocolEmptyError));
return;
}
if (instanceUrlET.equals("")) {
Toasty.error(ctx, getResources().getString(R.string.emptyFieldURL));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.emptyFieldURL));
return;
}
if (loginToken.equals("")) {
Toasty.error(ctx, getResources().getString(R.string.loginTokenError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.loginTokenError));
return;
}
@ -132,7 +137,8 @@ public class AddNewAccountActivity extends BaseActivity {
} catch (Exception e) {
Toasty.error(ctx, getResources().getString(R.string.malformedUrl));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.malformedUrl));
}
}
@ -157,8 +163,10 @@ public class AddNewAccountActivity extends BaseActivity {
if (!Version.valid(version.getVersion())) {
Toasty.error(
ctx, getResources().getString(R.string.versionUnknown));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.versionUnknown));
return;
}
@ -192,12 +200,18 @@ public class AddNewAccountActivity extends BaseActivity {
login(instanceUrl, loginToken);
} else {
Toasty.warning(
SnackBar.error(
ctx,
getResources().getString(R.string.versionUnsupportedNew));
findViewById(android.R.id.content),
getString(R.string.versionUnsupportedNew));
login(instanceUrl, loginToken);
}
} else if (responseVersion.code() == 401) {
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.unauthorizedApiError));
} else if (responseVersion.code() == 403) {
login(instanceUrl, loginToken);
@ -213,9 +227,10 @@ public class AddNewAccountActivity extends BaseActivity {
public void onFailure(
@NonNull Call<ServerVersion> callVersion, @NonNull Throwable t) {
Log.e("onFailure-versionCheck", t.toString());
Toasty.error(
ctx, getResources().getString(R.string.genericServerResponseError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
}
});
}
@ -291,21 +306,20 @@ public class AddNewAccountActivity extends BaseActivity {
defaultPagingNumber);
UserAccount account = userAccountsApi.getAccountById((int) id);
AppUtil.switchToAccount(AddNewAccountActivity.this, account);
Toasty.success(
SnackBar.success(
ctx,
getResources().getString(R.string.accountAddedMessage));
findViewById(android.R.id.content),
getString(R.string.accountAddedMessage));
MainActivity.refActivity = true;
finish();
new Handler().postDelayed(() -> finish(), 3000);
} else {
UserAccount account =
userAccountsApi.getAccountByName(accountName);
if (account.isLoggedIn()) {
Toasty.warning(
SnackBar.error(
ctx,
getResources()
.getString(
R.string
.accountAlreadyExistsError));
findViewById(android.R.id.content),
getString(R.string.accountAlreadyExistsError));
AppUtil.switchToAccount(ctx, account);
} else {
userAccountsApi.updateTokenByAccountName(
@ -315,34 +329,31 @@ public class AddNewAccountActivity extends BaseActivity {
AddNewAccountActivity.this, account);
}
}
finish();
break;
case 401:
Toasty.error(
SnackBar.error(
ctx,
getResources().getString(R.string.unauthorizedApiError));
findViewById(android.R.id.content),
getString(R.string.unauthorizedApiError));
break;
default:
Toasty.error(
SnackBar.error(
ctx,
getResources()
.getString(
R.string.genericApiError, response.code()));
findViewById(android.R.id.content),
getString(R.string.genericApiError, response.code()));
}
}
@Override
public void onFailure(@NonNull Call<User> call, @NonNull Throwable t) {
Toasty.error(ctx, getResources().getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -94,7 +94,7 @@ public abstract class BaseActivity extends AppCompatActivity {
AppUtil.setAppLocale(getResources(), locale);
}
Notifications.startWorker(appCtx);
Notifications.startWorker(ctx);
}
public void onResume() {

View File

@ -2,15 +2,13 @@ package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.os.Handler;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
@ -29,8 +27,7 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateFileBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.NetworkStatusObserver;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import retrofit2.Call;
import retrofit2.Callback;
@ -72,16 +69,14 @@ public class CreateFileActivity extends BaseActivity {
repository = RepositoryContext.fromIntent(getIntent());
TextView toolbarTitle = binding.toolbarTitle;
binding.topAppBar.setNavigationOnClickListener(v -> finish());
binding.newFileName.requestFocus();
MenuItem create = binding.topAppBar.getMenu().getItem(0);
MenuItem update = binding.topAppBar.getMenu().getItem(1);
MenuItem delete = binding.topAppBar.getMenu().getItem(2);
update.setVisible(false);
delete.setVisible(false);
InputMethodManager inputMethodManager =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
assert inputMethodManager != null;
inputMethodManager.showSoftInput(binding.newFileName, InputMethodManager.SHOW_IMPLICIT);
binding.close.setOnClickListener(view -> finish());
binding.newFileContent.setOnTouchListener(
(touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
@ -103,12 +98,13 @@ public class CreateFileActivity extends BaseActivity {
filePath = getIntent().getStringExtra("filePath");
fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.deleteGenericTitle, filePath));
binding.newFileCreate.setText(R.string.deleteFile);
binding.topAppBar.setTitle(getString(R.string.deleteGenericTitle, filePath));
binding.newFileNameLayout.setVisibility(View.GONE);
binding.newFileContentLayout.setVisibility(View.GONE);
delete.setVisible(true);
create.setVisible(false);
update.setVisible(false);
}
if (getIntent().getStringExtra("filePath") != null
@ -118,20 +114,20 @@ public class CreateFileActivity extends BaseActivity {
filePath = getIntent().getStringExtra("filePath");
fileSha = getIntent().getStringExtra("fileSha");
toolbarTitle.setText(getString(R.string.editFileText, filePath));
binding.topAppBar.setTitle(getString(R.string.editFileText, filePath));
binding.newFileCreate.setText(R.string.editFile);
binding.newFileName.setText(filePath);
binding.newFileName.setEnabled(false);
binding.newFileName.setFocusable(false);
binding.newFileContent.setText(getIntent().getStringExtra("fileContents"));
update.setVisible(true);
create.setVisible(false);
delete.setVisible(false);
}
getBranches(repository.getOwner(), repository.getName());
disableProcessButton();
binding.openCodeEditor.setOnClickListener(
v ->
launchCodeEditorActivityForResult(
@ -139,13 +135,23 @@ public class CreateFileActivity extends BaseActivity {
FilenameUtils.getExtension(
String.valueOf(binding.newFileName.getText()))));
NetworkStatusObserver networkStatusObserver = NetworkStatusObserver.getInstance(ctx);
networkStatusObserver.registerNetworkStatusListener(
hasNetworkConnection ->
runOnUiThread(
() -> binding.newFileCreate.setEnabled(hasNetworkConnection)));
binding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
binding.newFileCreate.setOnClickListener(v -> processNewFile());
if (id == R.id.create) {
processNewFile();
return true;
} else if (id == R.id.update) {
processNewFile();
return true;
} else if (id == R.id.delete) {
processNewFile();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
}
public void launchCodeEditorActivityForResult(String fileContent, String fileExtension) {
@ -175,29 +181,39 @@ public class CreateFileActivity extends BaseActivity {
: "";
if (!AppUtil.hasNetworkConnection(appCtx)) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.checkNetConnection));
return;
}
if (((newFileName.isEmpty() || newFileContent.isEmpty())
&& fileAction != FILE_ACTION_DELETE)
|| newFileCommitMessage.isEmpty()) {
Toasty.error(ctx, getString(R.string.newFileRequiredFields));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.newFileRequiredFields));
return;
}
if (!AppUtil.checkStringsWithDash(newFileBranchName)) {
Toasty.error(ctx, getString(R.string.newFileInvalidBranchName));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.newFileInvalidBranchName));
return;
}
if (newFileCommitMessage.length() > 255) {
Toasty.warning(ctx, getString(R.string.newFileCommitMessageError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.newFileCommitMessageError));
return;
}
disableProcessButton();
switch (fileAction) {
case FILE_ACTION_CREATE:
createNewFile(
@ -264,39 +280,40 @@ public class CreateFileActivity extends BaseActivity {
switch (response.code()) {
case 201:
enableProcessButton();
Toasty.success(ctx, getString(R.string.newFileSuccessMessage));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.newFileSuccessMessage));
Intent result = new Intent();
result.putExtra("fileModified", true);
result.putExtra("fileAction", fileAction);
setResult(200, result);
RepoDetailActivity.updateFABActions = true;
finish();
new Handler().postDelayed(() -> finish(), 3000);
break;
case 401:
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
break;
case 404:
enableProcessButton();
Toasty.warning(ctx, getString(R.string.apiNotFound));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.apiNotFound));
break;
default:
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
break;
}
}
@Override
public void onFailure(@NonNull Call<FileResponse> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
public void onFailure(@NonNull Call<FileResponse> call, @NonNull Throwable t) {}
});
}
@ -332,9 +349,9 @@ public class CreateFileActivity extends BaseActivity {
switch (response.code()) {
case 200:
enableProcessButton();
Toasty.info(
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(
R.string.deleteFileMessage,
repository.getBranchRef()));
@ -342,33 +359,32 @@ public class CreateFileActivity extends BaseActivity {
result.putExtra("fileModified", true);
result.putExtra("fileAction", fileAction);
setResult(200, result);
finish();
new Handler().postDelayed(() -> finish(), 3000);
break;
case 401:
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
break;
case 404:
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.apiNotFound));
break;
default:
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
break;
}
}
@Override
public void onFailure(
@NonNull Call<FileDeleteResponse> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@NonNull Call<FileDeleteResponse> call, @NonNull Throwable t) {}
});
}
@ -406,38 +422,39 @@ public class CreateFileActivity extends BaseActivity {
switch (response.code()) {
case 200:
enableProcessButton();
Toasty.info(ctx, getString(R.string.editFileMessage, branchName));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.editFileMessage, branchName));
Intent result = new Intent();
result.putExtra("fileModified", true);
result.putExtra("fileAction", fileAction);
setResult(200, result);
finish();
new Handler().postDelayed(() -> finish(), 3000);
break;
case 401:
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
break;
case 404:
enableProcessButton();
Toasty.info(ctx, getString(R.string.apiNotFound));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.apiNotFound));
break;
default:
enableProcessButton();
Toasty.info(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
break;
}
}
@Override
public void onFailure(@NonNull Call<FileResponse> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
public void onFailure(@NonNull Call<FileResponse> call, @NonNull Throwable t) {}
});
}
@ -468,27 +485,14 @@ public class CreateFileActivity extends BaseActivity {
binding.newFileBranches.setAdapter(adapter);
binding.newFileBranches.setText(repository.getBranchRef(), false);
enableProcessButton();
}
}
@Override
public void onFailure(@NonNull Call<List<Branch>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
public void onFailure(@NonNull Call<List<Branch>> call, @NonNull Throwable t) {}
});
}
private void disableProcessButton() {
binding.newFileCreate.setEnabled(false);
}
private void enableProcessButton() {
binding.newFileCreate.setEnabled(true);
}
@Override
public void onResume() {
super.onResume();

View File

@ -1,27 +1,37 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.content.Context;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.datepicker.MaterialDatePicker;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.vdurmont.emoji.EmojiParser;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import org.gitnex.tea4j.v2.models.Attachment;
import org.gitnex.tea4j.v2.models.CreateIssueOption;
import org.gitnex.tea4j.v2.models.Issue;
import org.gitnex.tea4j.v2.models.Label;
@ -31,17 +41,20 @@ import org.mian.gitnex.R;
import org.mian.gitnex.actions.AssigneesActions;
import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.AssigneesListAdapter;
import org.mian.gitnex.adapters.AttachmentsAdapter;
import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateIssueBinding;
import org.mian.gitnex.databinding.BottomSheetAttachmentsBinding;
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.fragments.IssuesFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.attachments.AttachmentUtils;
import org.mian.gitnex.helpers.attachments.AttachmentsModel;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import retrofit2.Call;
import retrofit2.Callback;
@ -50,17 +63,15 @@ import retrofit2.Callback;
* @author M M Arif
*/
public class CreateIssueActivity extends BaseActivity
implements View.OnClickListener,
LabelsListAdapter.LabelsListAdapterListener,
AssigneesListAdapter.AssigneesListAdapterListener {
implements LabelsListAdapter.LabelsListAdapterListener,
AssigneesListAdapter.AssigneesListAdapterListener,
AttachmentsAdapter.AttachmentsReceiverListener {
private final List<Label> labelsList = new ArrayList<>();
private final LinkedHashMap<String, Milestone> milestonesList = new LinkedHashMap<>();
private final List<User> assigneesList = new ArrayList<>();
private ActivityCreateIssueBinding viewBinding;
private View.OnClickListener onClickListener;
private int milestoneId;
private Date currentDate = null;
private RepositoryContext repository;
private LabelsListAdapter labelsAdapter;
private AssigneesListAdapter assigneesAdapter;
@ -69,6 +80,9 @@ public class CreateIssueActivity extends BaseActivity
private List<String> assigneesListData = new ArrayList<>();
private boolean renderMd = false;
private RepositoryContext repositoryContext;
private static List<AttachmentsModel> attachmentsList;
private AttachmentsAdapter attachmentsAdapter;
private static final List<Uri> contentUri = new ArrayList<>();
@SuppressLint("ClickableViewAccessibility")
@Override
@ -78,15 +92,9 @@ public class CreateIssueActivity extends BaseActivity
viewBinding = ActivityCreateIssueBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
setSupportActionBar(viewBinding.toolbar);
repositoryContext = RepositoryContext.fromIntent(getIntent());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx, R.style.ThemeOverlay_Material3_Dialog_Alert);
@ -94,9 +102,10 @@ public class CreateIssueActivity extends BaseActivity
int resultLimit = Constants.getCurrentResultLimit(ctx);
viewBinding.newIssueTitle.requestFocus();
assert imm != null;
imm.showSoftInput(viewBinding.newIssueTitle, InputMethodManager.SHOW_IMPLICIT);
attachmentsList = new ArrayList<>();
attachmentsAdapter = new AttachmentsAdapter(attachmentsList, ctx);
AttachmentsAdapter.setAttachmentsReceiveListener(this);
viewBinding.newIssueDescription.setOnTouchListener(
(touchView, motionEvent) -> {
@ -115,30 +124,62 @@ public class CreateIssueActivity extends BaseActivity
new AssigneesListAdapter(
ctx, assigneesList, CreateIssueActivity.this, assigneesListData);
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
showDatePickerDialog();
viewBinding.newIssueAssigneesList.setOnClickListener(this);
viewBinding.newIssueLabels.setOnClickListener(this);
viewBinding.newIssueDueDate.setOnClickListener(this);
viewBinding.newIssueDueDateLayout.setEndIconOnClickListener(
view -> viewBinding.newIssueDueDate.setText(""));
viewBinding.topAppBar.setNavigationOnClickListener(
v -> {
finish();
contentUri.clear();
});
viewBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
if (id == R.id.markdown) {
if (!renderMd) {
Markdown.render(
ctx,
EmojiParser.parseToUnicode(
Objects.requireNonNull(
viewBinding.newIssueDescription
.getText())
.toString()),
viewBinding.markdownPreview,
repositoryContext);
viewBinding.markdownPreview.setVisibility(View.VISIBLE);
viewBinding.newIssueDescriptionLayout.setVisibility(View.GONE);
renderMd = true;
} else {
viewBinding.markdownPreview.setVisibility(View.GONE);
viewBinding.newIssueDescriptionLayout.setVisibility(View.VISIBLE);
renderMd = false;
}
return true;
} else if (id == R.id.create) {
processNewIssue();
return true;
} else if (id == R.id.attachment) {
checkForAttachments();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
getMilestones(repository.getOwner(), repository.getName(), resultLimit);
disableProcessButton();
viewBinding.newIssueLabels.setOnClickListener(newIssueLabels -> showLabels());
viewBinding.newIssueAssigneesList.setOnClickListener(
newIssueAssigneesList -> showAssignees());
if (!connToInternet) {
viewBinding.createNewIssueButton.setEnabled(false);
} else {
viewBinding.createNewIssueButton.setOnClickListener(this);
}
if (!repository.getPermissions().isPush()) {
viewBinding.newIssueAssigneesListLayout.setVisibility(View.GONE);
viewBinding.newIssueMilestoneSpinnerLayout.setVisibility(View.GONE);
@ -147,46 +188,148 @@ public class CreateIssueActivity extends BaseActivity
}
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
ActivityResultLauncher<Intent> startActivityForResult =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
assert data != null;
contentUri.add(data.getData());
attachmentsList.add(
new AttachmentsModel(
AttachmentUtils.queryName(ctx, data.getData()),
data.getData()));
attachmentsAdapter.updateList(attachmentsList);
}
});
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.markdown_switcher, menu);
return true;
public void onDestroy() {
AttachmentsAdapter.setAttachmentsReceiveListener(null);
super.onDestroy();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
public void setAttachmentsData(Uri filename) {
contentUri.remove(filename);
}
int id = item.getItemId();
private void checkForAttachments() {
if (id == R.id.markdown) {
if (contentUri.size() > 0) {
if (!renderMd) {
Markdown.render(
ctx,
EmojiParser.parseToUnicode(
Objects.requireNonNull(viewBinding.newIssueDescription.getText())
.toString()),
viewBinding.markdownPreview,
repositoryContext);
BottomSheetAttachmentsBinding bottomSheetAttachmentsBinding =
BottomSheetAttachmentsBinding.inflate(getLayoutInflater());
viewBinding.markdownPreview.setVisibility(View.VISIBLE);
viewBinding.newIssueDescriptionLayout.setVisibility(View.GONE);
renderMd = true;
} else {
viewBinding.markdownPreview.setVisibility(View.GONE);
viewBinding.newIssueDescriptionLayout.setVisibility(View.VISIBLE);
renderMd = false;
}
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(ctx);
return true;
bottomSheetAttachmentsBinding.addAttachment.setOnClickListener(
v1 -> openFileAttachmentActivity());
bottomSheetAttachmentsBinding.recyclerViewAttachments.setHasFixedSize(true);
bottomSheetAttachmentsBinding.recyclerViewAttachments.setLayoutManager(
new LinearLayoutManager(ctx));
bottomSheetAttachmentsBinding.recyclerViewAttachments.setAdapter(attachmentsAdapter);
bottomSheetDialog.setContentView(bottomSheetAttachmentsBinding.getRoot());
bottomSheetDialog.show();
} else {
return super.onOptionsItemSelected(item);
openFileAttachmentActivity();
}
}
private void openFileAttachmentActivity() {
Intent data = new Intent(Intent.ACTION_GET_CONTENT);
data.addCategory(Intent.CATEGORY_OPENABLE);
data.setType("*/*");
Intent intent = Intent.createChooser(data, "Choose a file");
startActivityForResult.launch(intent);
}
private void processAttachments(long issueIndex) {
for (int i = 0; i < contentUri.size(); i++) {
File file = AttachmentUtils.getFile(ctx, contentUri.get(i));
RequestBody requestFile =
RequestBody.create(
file,
MediaType.parse(
Objects.requireNonNull(
getContentResolver().getType(contentUri.get(i)))));
uploadAttachments(requestFile, issueIndex, file.getName());
}
}
private void uploadAttachments(RequestBody requestFile, long issueIndex, String filename1) {
Call<Attachment> call3 =
RetrofitClient.getApiInterface(ctx)
.issueCreateIssueAttachment(
requestFile,
repository.getOwner(),
repository.getName(),
issueIndex,
filename1);
call3.enqueue(
new Callback<>() {
@Override
public void onResponse(
@NonNull Call<Attachment> call,
@NonNull retrofit2.Response<Attachment> response2) {
if (response2.code() == 201) {
new Handler().postDelayed(() -> finish(), 3000);
} else if (response2.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else {
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.attachmentsSaveError));
}
}
@Override
public void onFailure(@NonNull Call<Attachment> call, @NonNull Throwable t) {
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
}
});
}
private void showDatePickerDialog() {
MaterialDatePicker.Builder<Long> builder = MaterialDatePicker.Builder.datePicker();
builder.setSelection(Calendar.getInstance().getTimeInMillis());
builder.setTitleText(R.string.newIssueDueDateTitle);
MaterialDatePicker<Long> materialDatePicker = builder.build();
viewBinding.newIssueDueDate.setOnClickListener(
v -> materialDatePicker.show(getSupportFragmentManager(), "DATE_PICKER"));
materialDatePicker.addOnPositiveButtonClickListener(
selection -> {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.setTimeInMillis(selection);
SimpleDateFormat format =
new SimpleDateFormat(
"yyyy-MM-dd", new Locale(tinyDB.getString("locale")));
String formattedDate = format.format(calendar.getTime());
viewBinding.newIssueDueDate.setText(formattedDate);
});
}
@Override
public void assigneesInterface(List<String> data) {
@ -255,8 +398,6 @@ public class CreateIssueActivity extends BaseActivity
private void processNewIssue() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newIssueTitleForm =
Objects.requireNonNull(viewBinding.newIssueTitle.getText()).toString();
String newIssueDescriptionForm =
@ -264,25 +405,20 @@ public class CreateIssueActivity extends BaseActivity
String newIssueDueDateForm =
Objects.requireNonNull(viewBinding.newIssueDueDate.getText()).toString();
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (newIssueTitleForm.equals("")) {
Toasty.error(ctx, getString(R.string.issueTitleEmpty));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.issueTitleEmpty));
return;
}
disableProcessButton();
createNewIssueFunc(
repository.getOwner(),
repository.getName(),
newIssueDescriptionForm,
milestoneId,
newIssueTitleForm);
newIssueTitleForm,
newIssueDueDateForm);
}
private void createNewIssueFunc(
@ -290,7 +426,8 @@ public class CreateIssueActivity extends BaseActivity
String repoName,
String newIssueDescriptionForm,
int newIssueMilestoneIdForm,
String newIssueTitleForm) {
String newIssueTitleForm,
String newIssueDueDateForm) {
ArrayList<Long> labelIds = new ArrayList<>();
for (Integer i : labelsIds) {
@ -300,7 +437,15 @@ public class CreateIssueActivity extends BaseActivity
CreateIssueOption createNewIssueJson = new CreateIssueOption();
createNewIssueJson.setBody(newIssueDescriptionForm);
createNewIssueJson.setMilestone((long) newIssueMilestoneIdForm);
createNewIssueJson.setDueDate(currentDate);
String[] date = newIssueDueDateForm.split("-");
if (!newIssueDueDateForm.equalsIgnoreCase("")) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Integer.parseInt(date[0]));
calendar.set(Calendar.MONTH, Integer.parseInt(date[1]));
calendar.set(Calendar.DATE, Integer.parseInt(date[2]));
Date dueDate = calendar.getTime();
createNewIssueJson.setDueDate(dueDate);
}
createNewIssueJson.setTitle(newIssueTitleForm);
createNewIssueJson.setAssignees(assigneesListData);
createNewIssueJson.setLabels(labelIds);
@ -320,37 +465,46 @@ public class CreateIssueActivity extends BaseActivity
if (response2.code() == 201) {
IssuesFragment.resumeIssues = true;
Toasty.success(ctx, getString(R.string.issueCreated));
enableProcessButton();
RepoDetailActivity.updateRepo = true;
MainActivity.reloadRepos = true;
finish();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.issueCreated));
assert response2.body() != null;
if (contentUri.size() > 0) {
processAttachments(response2.body().getNumber());
contentUri.clear();
} else {
new Handler().postDelayed(() -> finish(), 3000);
}
} else if (response2.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else {
Toasty.error(ctx, getString(R.string.genericError));
enableProcessButton();
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Issue> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
enableProcessButton();
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void getMilestones(String repoOwner, String repoName, int resultLimit) {
String msState = "open";
@ -396,7 +550,7 @@ public class CreateIssueActivity extends BaseActivity
new ArrayList<>(milestonesList.keySet()));
viewBinding.newIssueMilestoneSpinner.setAdapter(adapter);
enableProcessButton();
// enableProcessButton();
viewBinding.newIssueMilestoneSpinner.setOnItemClickListener(
(parent, view, position, id) -> {
@ -422,53 +576,14 @@ public class CreateIssueActivity extends BaseActivity
public void onFailure(
@NonNull Call<List<Milestone>> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
}
});
}
@Override
public void onClick(View v) {
if (v == viewBinding.newIssueDueDate) {
final Calendar c = Calendar.getInstance();
int mYear = c.get(Calendar.YEAR);
final int mMonth = c.get(Calendar.MONTH);
final int mDay = c.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog =
new DatePickerDialog(
this,
(view, year, monthOfYear, dayOfMonth) -> {
viewBinding.newIssueDueDate.setText(
getString(
R.string.setDueDate,
year,
(monthOfYear + 1),
dayOfMonth));
currentDate = new Date(year - 1900, monthOfYear, dayOfMonth);
},
mYear,
mMonth,
mDay);
datePickerDialog.show();
} else if (v == viewBinding.createNewIssueButton) {
processNewIssue();
}
}
private void disableProcessButton() {
viewBinding.createNewIssueButton.setEnabled(false);
}
private void enableProcessButton() {
viewBinding.createNewIssueButton.setEnabled(true);
}
@Override
public void onResume() {
super.onResume();

View File

@ -1,15 +1,15 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import android.os.Handler;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import com.skydoves.colorpickerview.ColorPickerDialog;
import com.skydoves.colorpickerview.flag.BubbleFlag;
import com.skydoves.colorpickerview.listeners.ColorEnvelopeListener;
import com.skydoves.colorpickerview.preference.ColorPickerPreferenceManager;
import java.util.Objects;
import org.gitnex.tea4j.v2.models.CreateLabelOption;
import org.gitnex.tea4j.v2.models.EditLabelOption;
@ -19,7 +19,7 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateLabelBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import org.mian.gitnex.viewmodels.LabelsViewModel;
import org.mian.gitnex.viewmodels.OrganizationLabelsViewModel;
@ -32,15 +32,11 @@ import retrofit2.Callback;
public class CreateLabelActivity extends BaseActivity {
public static boolean refreshLabels = false;
private ActivityCreateLabelBinding activityCreateLabelBinding;
private View.OnClickListener onClickListener;
private RepositoryContext repository;
private String labelColor = "";
private final View.OnClickListener createLabelListener = v -> processCreateLabel();
private String labelColorDefault = "";
private final View.OnClickListener updateLabelListener = v -> processUpdateLabel();
private ColorPickerPreferenceManager colorManager;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -50,9 +46,6 @@ public class CreateLabelActivity extends BaseActivity {
activityCreateLabelBinding = ActivityCreateLabelBinding.inflate(getLayoutInflater());
setContentView(activityCreateLabelBinding.getRoot());
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
repository = RepositoryContext.fromIntent(getIntent());
if (getIntent().getStringExtra("labelAction") != null
@ -66,26 +59,18 @@ public class CreateLabelActivity extends BaseActivity {
return;
}
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
activityCreateLabelBinding.topAppBar.setNavigationOnClickListener(v -> finish());
activityCreateLabelBinding.labelName.requestFocus();
assert imm != null;
imm.showSoftInput(activityCreateLabelBinding.labelName, InputMethodManager.SHOW_IMPLICIT);
colorManager = ColorPickerPreferenceManager.getInstance(this);
colorManager.clearSavedAllData();
activityCreateLabelBinding.colorPicker.setBackgroundColor(
colorManager.getColor("colorPickerDialogLabels", Color.RED));
final ColorPicker cp = new ColorPicker(CreateLabelActivity.this, 235, 113, 33);
MenuItem create = activityCreateLabelBinding.topAppBar.getMenu().getItem(0);
MenuItem update = activityCreateLabelBinding.topAppBar.getMenu().getItem(1);
update.setVisible(false);
initCloseListener();
activityCreateLabelBinding.close.setOnClickListener(onClickListener);
activityCreateLabelBinding.colorPicker.setOnClickListener(v -> cp.show());
cp.setCallback(
color -> {
// Log.i("#Hex no alpha", String.format("#%06X", (0xFFFFFF & color)));
activityCreateLabelBinding.colorPicker.setBackgroundColor(color);
labelColor = String.format("#%06X", (0xFFFFFF & color));
cp.dismiss();
});
activityCreateLabelBinding.colorPicker.setOnClickListener(v -> newColorPicker());
if (getIntent().getStringExtra("labelAction") != null
&& Objects.requireNonNull(getIntent().getStringExtra("labelAction"))
@ -96,28 +81,74 @@ public class CreateLabelActivity extends BaseActivity {
activityCreateLabelBinding.colorPicker.setBackgroundColor(labelColor_);
labelColorDefault = "#" + getIntent().getStringExtra("labelColor");
TextView toolbar_title = activityCreateLabelBinding.toolbarTitle;
toolbar_title.setText(getResources().getString(R.string.pageTitleLabelUpdate));
activityCreateLabelBinding.createLabelButton.setText(
getResources().getString(R.string.newUpdateButtonCopy));
activityCreateLabelBinding.topAppBar.setTitle(getString(R.string.pageTitleLabelUpdate));
update.setVisible(true);
create.setVisible(false);
activityCreateLabelBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
if (id == R.id.update) {
processUpdateLabel();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
activityCreateLabelBinding.createLabelButton.setOnClickListener(updateLabelListener);
return;
}
if (!connToInternet) {
activityCreateLabelBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
activityCreateLabelBinding.createLabelButton.setEnabled(false);
if (id == R.id.create) {
processCreateLabel();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
}
private void newColorPicker() {
ColorPickerDialog.Builder builder =
new ColorPickerDialog.Builder(this)
.setPreferenceName("colorPickerDialogLabels")
.setPositiveButton(
getString(R.string.okButton),
(ColorEnvelopeListener)
(envelope, clicked) -> {
activityCreateLabelBinding.colorPicker
.setBackgroundColor(envelope.getColor());
labelColor =
String.format(
"#%06X",
(0xFFFFFF & envelope.getColor()));
})
.attachAlphaSlideBar(true)
.attachBrightnessSlideBar(true)
.setBottomSpace(16);
builder.getColorPickerView().setFlagView(new BubbleFlag(this));
if (!labelColorDefault.equalsIgnoreCase("")) {
int labelColorCurrent = Color.parseColor(labelColorDefault);
builder.getColorPickerView().setInitialColor(labelColorCurrent);
} else {
activityCreateLabelBinding.createLabelButton.setOnClickListener(createLabelListener);
colorManager.setColor("colorPickerDialogLabels", Color.RED);
}
builder.getColorPickerView().setLifecycleOwner(this);
builder.show();
}
private void processUpdateLabel() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String updateLabelName =
Objects.requireNonNull(activityCreateLabelBinding.labelName.getText()).toString();
@ -130,25 +161,20 @@ public class CreateLabelActivity extends BaseActivity {
updateLabelColor = labelColor;
}
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (updateLabelName.equals("")) {
Toasty.error(ctx, getString(R.string.labelEmptyError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.labelEmptyError));
return;
}
if (!AppUtil.checkStrings(updateLabelName)) {
if (!AppUtil.checkLabel(updateLabelName)) {
Toasty.error(ctx, getString(R.string.labelNameError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.labelNameError));
return;
}
disableProcessButton();
patchLabel(
repository,
updateLabelName,
@ -158,8 +184,6 @@ public class CreateLabelActivity extends BaseActivity {
private void processCreateLabel() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newLabelName =
Objects.requireNonNull(activityCreateLabelBinding.labelName.getText()).toString();
String newLabelColor;
@ -174,25 +198,20 @@ public class CreateLabelActivity extends BaseActivity {
newLabelColor = labelColor;
}
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (newLabelName.equals("")) {
Toasty.error(ctx, getString(R.string.labelEmptyError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.labelEmptyError));
return;
}
if (!AppUtil.checkStrings(newLabelName)) {
if (!AppUtil.checkLabel(newLabelName)) {
Toasty.error(ctx, getString(R.string.labelNameError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.labelNameError));
return;
}
disableProcessButton();
createNewLabel(newLabelName, newLabelColor);
}
@ -230,17 +249,21 @@ public class CreateLabelActivity extends BaseActivity {
if (response.code() == 201) {
Toasty.success(ctx, getString(R.string.labelCreated));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.labelCreated));
refreshLabels = true;
finish();
new Handler().postDelayed(() -> finish(), 3000);
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@ -248,8 +271,6 @@ public class CreateLabelActivity extends BaseActivity {
public void onFailure(@NonNull Call<Label> call, @NonNull Throwable t) {
labelColor = "";
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
@ -298,18 +319,22 @@ public class CreateLabelActivity extends BaseActivity {
if (response.code() == 200) {
Toasty.success(ctx, getString(R.string.labelUpdated));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.labelUpdated));
refreshLabels = true;
finish();
new Handler().postDelayed(() -> finish(), 3000);
}
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@ -318,17 +343,10 @@ public class CreateLabelActivity extends BaseActivity {
labelColor = "";
labelColorDefault = "";
Log.e("onFailure", t.toString());
enableProcessButton();
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void deleteLabel(int labelId) {
Call<Void> call;
@ -358,7 +376,11 @@ public class CreateLabelActivity extends BaseActivity {
if (response.code() == 204) {
Toasty.success(ctx, getString(R.string.labelDeleteText));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.labelDeleteText));
if (getIntent().getStringExtra("type") != null
&& Objects.requireNonNull(
getIntent().getStringExtra("type"))
@ -377,27 +399,18 @@ public class CreateLabelActivity extends BaseActivity {
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else {
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {}
});
}
private void disableProcessButton() {
activityCreateLabelBinding.createLabelButton.setEnabled(false);
}
private void enableProcessButton() {
activityCreateLabelBinding.createLabelButton.setEnabled(true);
}
@Override
public void onResume() {
super.onResume();

View File

@ -1,30 +1,28 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.os.Handler;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import com.google.android.material.datepicker.MaterialDatePicker;
import com.vdurmont.emoji.EmojiParser;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;
import org.gitnex.tea4j.v2.models.CreateMilestoneOption;
import org.gitnex.tea4j.v2.models.Milestone;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateMilestoneBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import retrofit2.Call;
import retrofit2.Callback;
@ -32,13 +30,10 @@ import retrofit2.Callback;
/**
* @author M M Arif
*/
public class CreateMilestoneActivity extends BaseActivity implements View.OnClickListener {
public class CreateMilestoneActivity extends BaseActivity {
private ActivityCreateMilestoneBinding binding;
private View.OnClickListener onClickListener;
private RepositoryContext repository;
private Date currentDate = null;
private final View.OnClickListener createMilestoneListener = v -> processNewMilestone();
private boolean renderMd = false;
@SuppressLint("ClickableViewAccessibility")
@ -49,18 +44,15 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
binding = ActivityCreateMilestoneBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
repository = RepositoryContext.fromIntent(getIntent());
binding.milestoneTitle.requestFocus();
assert imm != null;
imm.showSoftInput(binding.milestoneTitle, InputMethodManager.SHOW_IMPLICIT);
binding.topAppBar.setNavigationOnClickListener(v -> finish());
MenuItem attachment = binding.topAppBar.getMenu().getItem(0);
attachment.setVisible(false);
showDatePickerDialog();
binding.milestoneDescription.setOnTouchListener(
(touchView, motionEvent) -> {
@ -74,78 +66,79 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
return false;
});
initCloseListener();
binding.close.setOnClickListener(onClickListener);
binding.milestoneDueDate.setOnClickListener(this);
binding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
if (!connToInternet) {
if (id == R.id.markdown) {
binding.createNewMilestoneButton.setEnabled(false);
} else {
if (!renderMd) {
Markdown.render(
ctx,
EmojiParser.parseToUnicode(
Objects.requireNonNull(
Objects.requireNonNull(
binding.milestoneDescription
.getText())
.toString())),
binding.markdownPreview);
binding.createNewMilestoneButton.setOnClickListener(createMilestoneListener);
}
binding.markdownPreview.setVisibility(View.VISIBLE);
binding.milestoneDescriptionLayout.setVisibility(View.GONE);
renderMd = true;
} else {
binding.markdownPreview.setVisibility(View.GONE);
binding.milestoneDescriptionLayout.setVisibility(View.VISIBLE);
renderMd = false;
}
return true;
} else if (id == R.id.create) {
processNewMilestone();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
private void showDatePickerDialog() {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.markdown_switcher, menu);
MaterialDatePicker.Builder<Long> builder = MaterialDatePicker.Builder.datePicker();
builder.setSelection(Calendar.getInstance().getTimeInMillis());
builder.setTitleText(R.string.newIssueDueDateTitle);
MaterialDatePicker<Long> materialDatePicker = builder.build();
return true;
}
binding.milestoneDueDate.setOnClickListener(
v -> materialDatePicker.show(getSupportFragmentManager(), "DATE_PICKER"));
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.markdown) {
if (!renderMd) {
Markdown.render(
ctx,
EmojiParser.parseToUnicode(
Objects.requireNonNull(
Objects.requireNonNull(
binding.milestoneDescription.getText())
.toString())),
binding.markdownPreview);
binding.markdownPreview.setVisibility(View.VISIBLE);
binding.milestoneDescriptionLayout.setVisibility(View.GONE);
renderMd = true;
} else {
binding.markdownPreview.setVisibility(View.GONE);
binding.milestoneDescriptionLayout.setVisibility(View.VISIBLE);
renderMd = false;
}
return true;
} else {
return super.onOptionsItemSelected(item);
}
materialDatePicker.addOnPositiveButtonClickListener(
selection -> {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.setTimeInMillis(selection);
SimpleDateFormat format =
new SimpleDateFormat(
"yyyy-MM-dd", new Locale(tinyDB.getString("locale")));
String formattedDate = format.format(calendar.getTime());
binding.milestoneDueDate.setText(formattedDate);
});
}
private void processNewMilestone() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newMilestoneTitle =
Objects.requireNonNull(binding.milestoneTitle.getText()).toString();
String newMilestoneDescription =
Objects.requireNonNull(binding.milestoneDescription.getText()).toString();
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
String milestoneDueDate =
Objects.requireNonNull(binding.milestoneDueDate.getText()).toString();
if (newMilestoneTitle.equals("")) {
Toasty.error(ctx, getString(R.string.milestoneNameErrorEmpty));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.milestoneNameErrorEmpty));
return;
}
@ -153,29 +146,41 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
if (newMilestoneDescription.length() > 255) {
Toasty.warning(ctx, getString(R.string.milestoneDescError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.milestoneDescError));
return;
}
}
disableProcessButton();
createNewMilestone(
repository.getOwner(),
repository.getName(),
newMilestoneTitle,
newMilestoneDescription);
newMilestoneDescription,
milestoneDueDate);
}
private void createNewMilestone(
String repoOwner,
String repoName,
String newMilestoneTitle,
String newMilestoneDescription) {
String newMilestoneDescription,
String milestoneDueDate) {
CreateMilestoneOption createMilestone = new CreateMilestoneOption();
createMilestone.setDescription(newMilestoneDescription);
createMilestone.setTitle(newMilestoneTitle);
createMilestone.setDueOn(currentDate);
String[] date = milestoneDueDate.split("-");
if (!milestoneDueDate.equalsIgnoreCase("")) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Integer.parseInt(date[0]));
calendar.set(Calendar.MONTH, Integer.parseInt(date[1]));
calendar.set(Calendar.DATE, Integer.parseInt(date[2]));
Date dueDate = calendar.getTime();
createMilestone.setDueOn(dueDate);
}
Call<Milestone> call;
@ -184,7 +189,7 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
.issueCreateMilestone(repoOwner, repoName, createMilestone);
call.enqueue(
new Callback<Milestone>() {
new Callback<>() {
@Override
public void onResponse(
@ -196,74 +201,30 @@ public class CreateMilestoneActivity extends BaseActivity implements View.OnClic
if (response.code() == 201) {
RepoDetailActivity.updateFABActions = true;
Toasty.success(ctx, getString(R.string.milestoneCreated));
enableProcessButton();
finish();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.milestoneCreated));
new Handler().postDelayed(() -> finish(), 3000);
}
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Milestone> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
public void onFailure(@NonNull Call<Milestone> call, @NonNull Throwable t) {}
});
}
@Override
public void onClick(View v) {
if (v == binding.milestoneDueDate) {
final Calendar c = Calendar.getInstance();
int mYear = c.get(Calendar.YEAR);
final int mMonth = c.get(Calendar.MONTH);
final int mDay = c.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog =
new DatePickerDialog(
this,
(view, year, monthOfYear, dayOfMonth) -> {
binding.milestoneDueDate.setText(
getString(
R.string.setDueDate,
year,
(monthOfYear + 1),
dayOfMonth));
currentDate = new Date(year - 1900, monthOfYear, dayOfMonth);
},
mYear,
mMonth,
mDay);
datePickerDialog.show();
}
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
binding.createNewMilestoneButton.setEnabled(false);
}
private void enableProcessButton() {
binding.createNewMilestoneButton.setEnabled(true);
}
@Override
public void onResume() {
super.onResume();

View File

@ -1,15 +1,11 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.os.Handler;
import android.util.Patterns;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import java.util.Objects;
import org.gitnex.tea4j.v2.models.CreateUserOption;
import org.gitnex.tea4j.v2.models.User;
import org.mian.gitnex.R;
@ -17,7 +13,7 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateNewUserBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import retrofit2.Call;
import retrofit2.Callback;
@ -26,93 +22,91 @@ import retrofit2.Callback;
*/
public class CreateNewUserActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private EditText fullName;
private EditText userUserName;
private EditText userEmail;
private EditText userPassword;
private Button createUserButton;
private final View.OnClickListener createNewUserListener = v -> processCreateNewUser();
private ActivityCreateNewUserBinding activityCreateNewUserBinding;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCreateNewUserBinding activityCreateNewUserBinding =
ActivityCreateNewUserBinding.inflate(getLayoutInflater());
activityCreateNewUserBinding = ActivityCreateNewUserBinding.inflate(getLayoutInflater());
setContentView(activityCreateNewUserBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
activityCreateNewUserBinding.topAppBar.setNavigationOnClickListener(
v -> {
finish();
});
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
MenuItem attachment = activityCreateNewUserBinding.topAppBar.getMenu().getItem(0);
MenuItem markdown = activityCreateNewUserBinding.topAppBar.getMenu().getItem(1);
attachment.setVisible(false);
markdown.setVisible(false);
ImageView closeActivity = activityCreateNewUserBinding.close;
createUserButton = activityCreateNewUserBinding.createUserButton;
fullName = activityCreateNewUserBinding.fullName;
userUserName = activityCreateNewUserBinding.userUserName;
userEmail = activityCreateNewUserBinding.userEmail;
userPassword = activityCreateNewUserBinding.userPassword;
activityCreateNewUserBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
fullName.requestFocus();
assert imm != null;
imm.showSoftInput(fullName, InputMethodManager.SHOW_IMPLICIT);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
if (!connToInternet) {
disableProcessButton();
} else {
createUserButton.setOnClickListener(createNewUserListener);
}
if (id == R.id.create) {
processCreateNewUser();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
}
private void processCreateNewUser() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newFullName = fullName.getText().toString().trim();
String newUserName = userUserName.getText().toString().trim();
String newUserEmail = userEmail.getText().toString().trim();
String newUserPassword = userPassword.getText().toString();
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
String newFullName =
Objects.requireNonNull(activityCreateNewUserBinding.fullName.getText())
.toString()
.trim();
String newUserName =
Objects.requireNonNull(activityCreateNewUserBinding.userUserName.getText())
.toString()
.trim();
String newUserEmail =
Objects.requireNonNull(activityCreateNewUserBinding.userEmail.getText())
.toString()
.trim();
String newUserPassword =
Objects.requireNonNull(activityCreateNewUserBinding.userPassword.getText())
.toString();
if (newFullName.equals("")
|| newUserName.equals("") | newUserEmail.equals("")
|| newUserPassword.equals("")) {
Toasty.error(ctx, getString(R.string.emptyFields));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.emptyFields));
return;
}
if (!AppUtil.checkStrings(newFullName)) {
Toasty.error(ctx, getString(R.string.userInvalidFullName));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.userInvalidFullName));
return;
}
if (!AppUtil.checkStringsWithAlphaNumeric(newUserName)) {
Toasty.error(ctx, getString(R.string.userInvalidUserName));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.userInvalidUserName));
return;
}
if (!Patterns.EMAIL_ADDRESS.matcher(newUserEmail).matches()) {
Toasty.error(ctx, getString(R.string.userInvalidEmail));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.userInvalidEmail));
return;
}
disableProcessButton();
createNewUser(newFullName, newUserName, newUserEmail, newUserPassword);
}
@ -129,7 +123,7 @@ public class CreateNewUserActivity extends BaseActivity {
Call<User> call = RetrofitClient.getApiInterface(ctx).adminCreateUser(createUser);
call.enqueue(
new Callback<User>() {
new Callback<>() {
@Override
public void onResponse(
@ -137,53 +131,43 @@ public class CreateNewUserActivity extends BaseActivity {
if (response.code() == 201) {
Toasty.success(ctx, getString(R.string.userCreatedText));
enableProcessButton();
finish();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.userCreatedText));
new Handler().postDelayed(() -> finish(), 3000);
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else if (response.code() == 403) {
enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.authorizeError));
} else if (response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.apiNotFound));
} else if (response.code() == 422) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.userExistsError));
SnackBar.warning(
ctx,
findViewById(android.R.id.content),
getString(R.string.userExistsError));
} else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<User> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
public void onFailure(@NonNull Call<User> call, @NonNull Throwable t) {}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
createUserButton.setEnabled(false);
}
private void enableProcessButton() {
createUserButton.setEnabled(true);
}
}

View File

@ -1,16 +1,12 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.os.Handler;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import java.util.Objects;
import org.gitnex.tea4j.v2.models.CreateOrgOption;
import org.gitnex.tea4j.v2.models.Organization;
import org.mian.gitnex.R;
@ -19,7 +15,7 @@ import org.mian.gitnex.databinding.ActivityCreateOrganizationBinding;
import org.mian.gitnex.fragments.OrganizationsFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import retrofit2.Call;
import retrofit2.Callback;
@ -28,13 +24,7 @@ import retrofit2.Callback;
*/
public class CreateOrganizationActivity extends BaseActivity {
public ImageView closeActivity;
private View.OnClickListener onClickListener;
private Button createOrganizationButton;
private EditText orgName;
private EditText orgDesc;
private final View.OnClickListener createOrgListener = v -> processNewOrganization();
private ActivityCreateOrganizationBinding activityCreateOrganizationBinding;
@SuppressLint("ClickableViewAccessibility")
@Override
@ -42,24 +32,18 @@ public class CreateOrganizationActivity extends BaseActivity {
super.onCreate(savedInstanceState);
ActivityCreateOrganizationBinding activityCreateOrganizationBinding =
activityCreateOrganizationBinding =
ActivityCreateOrganizationBinding.inflate(getLayoutInflater());
setContentView(activityCreateOrganizationBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
MenuItem attachment = activityCreateOrganizationBinding.topAppBar.getMenu().getItem(0);
MenuItem markdown = activityCreateOrganizationBinding.topAppBar.getMenu().getItem(1);
attachment.setVisible(false);
markdown.setVisible(false);
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
activityCreateOrganizationBinding.topAppBar.setNavigationOnClickListener(v -> finish());
closeActivity = activityCreateOrganizationBinding.close;
orgName = activityCreateOrganizationBinding.newOrganizationName;
orgDesc = activityCreateOrganizationBinding.newOrganizationDescription;
orgName.requestFocus();
assert imm != null;
imm.showSoftInput(orgName, InputMethodManager.SHOW_IMPLICIT);
orgDesc.setOnTouchListener(
activityCreateOrganizationBinding.newOrganizationDescription.setOnTouchListener(
(touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
@ -71,56 +55,53 @@ public class CreateOrganizationActivity extends BaseActivity {
return false;
});
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
activityCreateOrganizationBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
createOrganizationButton = activityCreateOrganizationBinding.createNewOrganizationButton;
if (!connToInternet) {
createOrganizationButton.setEnabled(false);
} else {
createOrganizationButton.setOnClickListener(createOrgListener);
}
}
private void initCloseListener() {
onClickListener = view -> finish();
if (id == R.id.create) {
processNewOrganization();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
}
private void processNewOrganization() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newOrgName = orgName.getText().toString();
String newOrgDesc = orgDesc.getText().toString();
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
String newOrgName =
Objects.requireNonNull(
activityCreateOrganizationBinding.newOrganizationName.getText())
.toString();
String newOrgDesc =
Objects.requireNonNull(
activityCreateOrganizationBinding.newOrganizationDescription
.getText())
.toString();
if (!newOrgDesc.equals("")) {
if (newOrgDesc.length() > 255) {
Toasty.warning(ctx, getString(R.string.orgDescError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.orgDescError));
return;
}
}
if (newOrgName.equals("")) {
Toasty.error(ctx, getString(R.string.orgNameErrorEmpty));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.orgNameErrorEmpty));
} else if (!AppUtil.checkStrings(newOrgName)) {
Toasty.warning(ctx, getString(R.string.orgNameErrorInvalid));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.orgNameErrorInvalid));
} else {
disableProcessButton();
createNewOrganization(newOrgName, newOrgDesc);
}
}
@ -134,7 +115,7 @@ public class CreateOrganizationActivity extends BaseActivity {
Call<Organization> call = RetrofitClient.getApiInterface(ctx).orgCreate(createOrganization);
call.enqueue(
new Callback<Organization>() {
new Callback<>() {
@Override
public void onResponse(
@ -143,51 +124,46 @@ public class CreateOrganizationActivity extends BaseActivity {
if (response.code() == 201) {
OrganizationsFragment.orgCreated = true;
enableProcessButton();
Toasty.success(ctx, getString(R.string.orgCreated));
finish();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.orgCreated));
new Handler().postDelayed(() -> finish(), 3000);
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else if (response.code() == 409) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.orgExistsError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.orgExistsError));
} else if (response.code() == 422) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.orgExistsError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.orgExistsError));
} else {
if (response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.apiNotFound));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.apiNotFound));
} else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
}
@Override
public void onFailure(@NonNull Call<Organization> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
public void onFailure(@NonNull Call<Organization> call, @NonNull Throwable t) {}
});
}
private void disableProcessButton() {
createOrganizationButton.setEnabled(false);
}
private void enableProcessButton() {
createOrganizationButton.setEnabled(true);
}
}

View File

@ -1,26 +1,37 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.datepicker.MaterialDatePicker;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.vdurmont.emoji.EmojiParser;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import org.gitnex.tea4j.v2.models.Attachment;
import org.gitnex.tea4j.v2.models.Branch;
import org.gitnex.tea4j.v2.models.CreatePullRequestOption;
import org.gitnex.tea4j.v2.models.Label;
@ -28,14 +39,19 @@ import org.gitnex.tea4j.v2.models.Milestone;
import org.gitnex.tea4j.v2.models.PullRequest;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.AttachmentsAdapter;
import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreatePrBinding;
import org.mian.gitnex.databinding.BottomSheetAttachmentsBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.fragments.PullRequestsFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.attachments.AttachmentUtils;
import org.mian.gitnex.helpers.attachments.AttachmentsModel;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import retrofit2.Call;
import retrofit2.Callback;
@ -44,22 +60,24 @@ import retrofit2.Callback;
* @author M M Arif
*/
public class CreatePullRequestActivity extends BaseActivity
implements LabelsListAdapter.LabelsListAdapterListener {
implements LabelsListAdapter.LabelsListAdapterListener,
AttachmentsAdapter.AttachmentsReceiverListener {
private final List<String> assignees = new ArrayList<>();
LinkedHashMap<String, Milestone> milestonesList = new LinkedHashMap<>();
List<String> branchesList = new ArrayList<>();
List<Label> labelsList = new ArrayList<>();
private View.OnClickListener onClickListener;
private ActivityCreatePrBinding viewBinding;
private List<Integer> labelsIds = new ArrayList<>();
private int milestoneId;
private Date currentDate = null;
private RepositoryContext repository;
private LabelsListAdapter labelsAdapter;
private MaterialAlertDialogBuilder materialAlertDialogBuilder;
private boolean renderMd = false;
private RepositoryContext repositoryContext;
private static List<AttachmentsModel> attachmentsList;
private AttachmentsAdapter attachmentsAdapter;
private static final List<Uri> contentUri = new ArrayList<>();
@SuppressLint("ClickableViewAccessibility")
@Override
@ -69,7 +87,6 @@ public class CreatePullRequestActivity extends BaseActivity
viewBinding = ActivityCreatePrBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
setSupportActionBar(viewBinding.toolbar);
repositoryContext = RepositoryContext.fromIntent(getIntent());
@ -78,6 +95,11 @@ public class CreatePullRequestActivity extends BaseActivity
repository = RepositoryContext.fromIntent(getIntent());
attachmentsList = new ArrayList<>();
attachmentsAdapter = new AttachmentsAdapter(attachmentsList, ctx);
AttachmentsAdapter.setAttachmentsReceiveListener(this);
int resultLimit = Constants.getCurrentResultLimit(ctx);
viewBinding.prBody.setOnTouchListener(
@ -95,22 +117,55 @@ public class CreatePullRequestActivity extends BaseActivity
labelsAdapter =
new LabelsListAdapter(labelsList, CreatePullRequestActivity.this, labelsIds);
ImageView closeActivity = findViewById(R.id.close);
showDatePickerDialog();
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
viewBinding.topAppBar.setNavigationOnClickListener(
v -> {
finish();
contentUri.clear();
});
viewBinding.prDueDate.setOnClickListener(dueDate -> setDueDate());
viewBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
disableProcessButton();
if (id == R.id.markdown) {
if (!renderMd) {
Markdown.render(
ctx,
EmojiParser.parseToUnicode(
Objects.requireNonNull(viewBinding.prBody.getText())
.toString()),
viewBinding.markdownPreview,
repositoryContext);
viewBinding.markdownPreview.setVisibility(View.VISIBLE);
viewBinding.prBodyLayout.setVisibility(View.GONE);
renderMd = true;
} else {
viewBinding.markdownPreview.setVisibility(View.GONE);
viewBinding.prBodyLayout.setVisibility(View.VISIBLE);
renderMd = false;
}
return true;
} else if (id == R.id.create) {
processPullRequest();
return true;
} else if (id == R.id.attachment) {
checkForAttachments();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
getMilestones(repository.getOwner(), repository.getName(), resultLimit);
getBranches(repository.getOwner(), repository.getName());
viewBinding.prLabels.setOnClickListener(prLabels -> showLabels());
viewBinding.createPr.setOnClickListener(createPr -> processPullRequest());
if (!repository.getPermissions().isPush()) {
viewBinding.prDueDateLayout.setVisibility(View.GONE);
viewBinding.prLabelsLayout.setVisibility(View.GONE);
@ -118,51 +173,130 @@ public class CreatePullRequestActivity extends BaseActivity
}
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
ActivityResultLauncher<Intent> startActivityForResult =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
assert data != null;
contentUri.add(data.getData());
attachmentsList.add(
new AttachmentsModel(
AttachmentUtils.queryName(ctx, data.getData()),
data.getData()));
attachmentsAdapter.updateList(attachmentsList);
}
});
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.markdown_switcher, menu);
return true;
public void onDestroy() {
AttachmentsAdapter.setAttachmentsReceiveListener(null);
super.onDestroy();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
public void setAttachmentsData(Uri filename) {
contentUri.remove(filename);
}
int id = item.getItemId();
private void checkForAttachments() {
if (id == R.id.markdown) {
if (contentUri.size() > 0) {
if (!renderMd) {
Markdown.render(
ctx,
EmojiParser.parseToUnicode(
Objects.requireNonNull(viewBinding.prBody.getText()).toString()),
viewBinding.markdownPreview,
repositoryContext);
BottomSheetAttachmentsBinding bottomSheetAttachmentsBinding =
BottomSheetAttachmentsBinding.inflate(getLayoutInflater());
viewBinding.markdownPreview.setVisibility(View.VISIBLE);
viewBinding.prBodyLayout.setVisibility(View.GONE);
renderMd = true;
} else {
viewBinding.markdownPreview.setVisibility(View.GONE);
viewBinding.prBodyLayout.setVisibility(View.VISIBLE);
renderMd = false;
}
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(ctx);
return true;
bottomSheetAttachmentsBinding.addAttachment.setOnClickListener(
v1 -> openFileAttachmentActivity());
bottomSheetAttachmentsBinding.recyclerViewAttachments.setHasFixedSize(true);
bottomSheetAttachmentsBinding.recyclerViewAttachments.setLayoutManager(
new LinearLayoutManager(ctx));
bottomSheetAttachmentsBinding.recyclerViewAttachments.setAdapter(attachmentsAdapter);
bottomSheetDialog.setContentView(bottomSheetAttachmentsBinding.getRoot());
bottomSheetDialog.show();
} else {
return super.onOptionsItemSelected(item);
openFileAttachmentActivity();
}
}
private void openFileAttachmentActivity() {
Intent data = new Intent(Intent.ACTION_GET_CONTENT);
data.addCategory(Intent.CATEGORY_OPENABLE);
data.setType("*/*");
Intent intent = Intent.createChooser(data, "Choose a file");
startActivityForResult.launch(intent);
}
private void processAttachments(long issueIndex) {
for (int i = 0; i < contentUri.size(); i++) {
File file = AttachmentUtils.getFile(ctx, contentUri.get(i));
RequestBody requestFile =
RequestBody.create(
file, MediaType.parse(getContentResolver().getType(contentUri.get(i))));
uploadAttachments(requestFile, issueIndex, file.getName());
}
}
private void uploadAttachments(RequestBody requestFile, long issueIndex, String filename1) {
Call<Attachment> call3 =
RetrofitClient.getApiInterface(ctx)
.issueCreateIssueAttachment(
requestFile,
repository.getOwner(),
repository.getName(),
issueIndex,
filename1);
call3.enqueue(
new Callback<>() {
@Override
public void onResponse(
@NonNull Call<Attachment> call,
@NonNull retrofit2.Response<Attachment> response2) {
if (response2.code() == 201) {
new Handler().postDelayed(() -> finish(), 3000);
} else if (response2.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else {
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.attachmentsSaveError));
}
}
@Override
public void onFailure(@NonNull Call<Attachment> call, @NonNull Throwable t) {
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
}
});
}
private void processPullRequest() {
String prTitle = String.valueOf(viewBinding.prTitle.getText());
String prDescription = String.valueOf(viewBinding.prBody.getText());
String mergeInto = viewBinding.mergeIntoBranchSpinner.getText().toString();
String pullFrom = viewBinding.pullFromBranchSpinner.getText().toString();
String prDueDate = Objects.requireNonNull(viewBinding.prDueDate.getText()).toString();
assignees.add("");
@ -173,19 +307,23 @@ public class CreatePullRequestActivity extends BaseActivity
if (prTitle.matches("")) {
Toasty.error(ctx, getString(R.string.titleError));
SnackBar.error(ctx, findViewById(android.R.id.content), getString(R.string.titleError));
} else if (mergeInto.matches("")) {
Toasty.error(ctx, getString(R.string.mergeIntoError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.mergeIntoError));
} else if (pullFrom.matches("")) {
Toasty.error(ctx, getString(R.string.pullFromError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.pullFromError));
} else if (pullFrom.equals(mergeInto)) {
Toasty.error(ctx, getString(R.string.sameBranchesError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.sameBranchesError));
} else {
createPullRequest(prTitle, prDescription, mergeInto, pullFrom, milestoneId, assignees);
createPullRequest(
prTitle, prDescription, mergeInto, pullFrom, milestoneId, assignees, prDueDate);
}
}
@ -195,7 +333,8 @@ public class CreatePullRequestActivity extends BaseActivity
String mergeInto,
String pullFrom,
int milestoneId,
List<String> assignees) {
List<String> assignees,
String prDueDate) {
ArrayList<Long> labelIds = new ArrayList<>();
for (Integer i : labelsIds) {
@ -210,7 +349,15 @@ public class CreatePullRequestActivity extends BaseActivity
createPullRequest.setBase(mergeInto);
createPullRequest.setHead(pullFrom);
createPullRequest.setLabels(labelIds);
createPullRequest.setDueDate(currentDate);
String[] date = prDueDate.split("-");
if (!prDueDate.equalsIgnoreCase("")) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Integer.parseInt(date[0]));
calendar.set(Calendar.MONTH, Integer.parseInt(date[1]));
calendar.set(Calendar.DATE, Integer.parseInt(date[2]));
Date dueDate = calendar.getTime();
createPullRequest.setDueDate(dueDate);
}
Call<PullRequest> transferCall =
RetrofitClient.getApiInterface(ctx)
@ -225,40 +372,78 @@ public class CreatePullRequestActivity extends BaseActivity
@NonNull Call<PullRequest> call,
@NonNull retrofit2.Response<PullRequest> response) {
disableProcessButton();
if (response.code() == 201) {
Toasty.success(ctx, getString(R.string.prCreateSuccess));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.prCreateSuccess));
RepoDetailActivity.updateRepo = true;
PullRequestsFragment.resumePullRequests = true;
MainActivity.reloadRepos = true;
finish();
if (contentUri.size() > 0) {
assert response.body() != null;
processAttachments(response.body().getNumber());
contentUri.clear();
} else {
new Handler().postDelayed(() -> finish(), 3000);
}
} else if (response.code() == 409
|| response.message().equals("Conflict")) {
enableProcessButton();
Toasty.error(ctx, getString(R.string.prAlreadyExists));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.prAlreadyExists));
} else if (response.code() == 404) {
enableProcessButton();
Toasty.error(ctx, getString(R.string.apiNotFound));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.apiNotFound));
} else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<PullRequest> call, @NonNull Throwable t) {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericServerResponseError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
}
});
}
private void showDatePickerDialog() {
MaterialDatePicker.Builder<Long> builder = MaterialDatePicker.Builder.datePicker();
builder.setSelection(Calendar.getInstance().getTimeInMillis());
builder.setTitleText(R.string.newIssueDueDateTitle);
MaterialDatePicker<Long> materialDatePicker = builder.build();
viewBinding.prDueDate.setOnClickListener(
v -> materialDatePicker.show(getSupportFragmentManager(), "DATE_PICKER"));
materialDatePicker.addOnPositiveButtonClickListener(
selection -> {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.setTimeInMillis(selection);
SimpleDateFormat format =
new SimpleDateFormat(
"yyyy-MM-dd", new Locale(tinyDB.getString("locale")));
String formattedDate = format.format(calendar.getTime());
viewBinding.prDueDate.setText(formattedDate);
});
}
@Override
public void labelsInterface(List<String> data) {
@ -325,7 +510,6 @@ public class CreatePullRequestActivity extends BaseActivity
viewBinding.mergeIntoBranchSpinner.setAdapter(adapter);
viewBinding.pullFromBranchSpinner.setAdapter(adapter);
enableProcessButton();
}
}
}
@ -333,7 +517,10 @@ public class CreatePullRequestActivity extends BaseActivity
@Override
public void onFailure(@NonNull Call<List<Branch>> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
}
});
}
@ -382,7 +569,6 @@ public class CreatePullRequestActivity extends BaseActivity
new ArrayList<>(milestonesList.keySet()));
viewBinding.milestonesSpinner.setAdapter(adapter);
enableProcessButton();
viewBinding.milestonesSpinner.setOnItemClickListener(
(parent, view, position, id) -> {
@ -407,51 +593,14 @@ public class CreatePullRequestActivity extends BaseActivity
public void onFailure(
@NonNull Call<List<Milestone>> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
}
});
}
private void setDueDate() {
final Calendar c = Calendar.getInstance();
int mYear = c.get(Calendar.YEAR);
final int mMonth = c.get(Calendar.MONTH);
final int mDay = c.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog =
new DatePickerDialog(
this,
(view, year, monthOfYear, dayOfMonth) -> {
viewBinding.prDueDate.setText(
getString(
R.string.setDueDate,
year,
(monthOfYear + 1),
dayOfMonth));
currentDate = new Date(year - 1900, monthOfYear, dayOfMonth);
},
mYear,
mMonth,
mDay);
datePickerDialog.show();
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
viewBinding.createPr.setEnabled(false);
}
private void enableProcessButton() {
viewBinding.createPr.setEnabled(true);
}
@Override
public void onResume() {
super.onResume();

View File

@ -1,15 +1,10 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import com.vdurmont.emoji.EmojiParser;
@ -25,9 +20,8 @@ import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateReleaseBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import retrofit2.Call;
import retrofit2.Callback;
@ -39,10 +33,8 @@ public class CreateReleaseActivity extends BaseActivity {
private ActivityCreateReleaseBinding binding;
List<String> branchesList = new ArrayList<>();
private View.OnClickListener onClickListener;
private String selectedBranch;
private RepositoryContext repository;
private final View.OnClickListener createReleaseListener = v -> processNewRelease();
private boolean renderMd = false;
@SuppressLint("ClickableViewAccessibility")
@ -53,19 +45,9 @@ public class CreateReleaseActivity extends BaseActivity {
binding = ActivityCreateReleaseBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
repository = RepositoryContext.fromIntent(getIntent());
binding.releaseTitle.requestFocus();
assert imm != null;
imm.showSoftInput(binding.releaseTitle, InputMethodManager.SHOW_IMPLICIT);
binding.releaseContent.setOnTouchListener(
(touchView, motionEvent) -> {
touchView.getParent().requestDisallowInterceptTouchEvent(true);
@ -78,90 +60,72 @@ public class CreateReleaseActivity extends BaseActivity {
return false;
});
initCloseListener();
binding.close.setOnClickListener(onClickListener);
binding.topAppBar.setNavigationOnClickListener(
v -> {
finish();
});
binding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
if (id == R.id.markdown) {
if (!renderMd) {
Markdown.render(
ctx,
EmojiParser.parseToUnicode(
Objects.requireNonNull(
Objects.requireNonNull(
binding.releaseContent
.getText())
.toString())),
binding.markdownPreview);
binding.markdownPreview.setVisibility(View.VISIBLE);
binding.releaseContentLayout.setVisibility(View.GONE);
renderMd = true;
} else {
binding.markdownPreview.setVisibility(View.GONE);
binding.releaseContentLayout.setVisibility(View.VISIBLE);
renderMd = false;
}
return true;
} else if (id == R.id.create) {
processNewRelease();
return true;
} else if (id == R.id.create_tag) {
createNewTag();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
getBranches(repository.getOwner(), repository.getName());
disableProcessButton();
if (!connToInternet) {
disableProcessButton();
} else {
binding.createNewRelease.setOnClickListener(createReleaseListener);
}
binding.createNewTag.setOnClickListener(v -> createNewTag());
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.markdown_switcher, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.markdown) {
if (!renderMd) {
Markdown.render(
ctx,
EmojiParser.parseToUnicode(
Objects.requireNonNull(
Objects.requireNonNull(binding.releaseContent.getText())
.toString())),
binding.markdownPreview);
binding.markdownPreview.setVisibility(View.VISIBLE);
binding.releaseContentLayout.setVisibility(View.GONE);
renderMd = true;
} else {
binding.markdownPreview.setVisibility(View.GONE);
binding.releaseContentLayout.setVisibility(View.VISIBLE);
renderMd = false;
}
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
private void createNewTag() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String tagName = Objects.requireNonNull(binding.releaseTagName.getText()).toString();
String message =
Objects.requireNonNull(binding.releaseTitle.getText()).toString()
Objects.requireNonNull(binding.releaseTitle.getText())
+ "\n\n"
+ Objects.requireNonNull(binding.releaseContent.getText()).toString();
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
+ Objects.requireNonNull(binding.releaseContent.getText());
if (tagName.equals("")) {
Toasty.error(ctx, getString(R.string.tagNameErrorEmpty));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.tagNameErrorEmpty));
return;
}
if (selectedBranch == null) {
Toasty.error(ctx, getString(R.string.selectBranchError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.selectBranchError));
return;
}
disableProcessButton();
CreateTagOption createReleaseJson = new CreateTagOption();
createReleaseJson.setMessage(message);
createReleaseJson.setTagName(tagName);
@ -173,7 +137,7 @@ public class CreateReleaseActivity extends BaseActivity {
repository.getOwner(), repository.getName(), createReleaseJson);
call.enqueue(
new Callback<Tag>() {
new Callback<>() {
@Override
public void onResponse(
@ -182,35 +146,38 @@ public class CreateReleaseActivity extends BaseActivity {
if (response.code() == 201) {
RepoDetailActivity.updateFABActions = true;
Toasty.success(ctx, getString(R.string.tagCreated));
finish();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.tagCreated));
new Handler().postDelayed(() -> finish(), 3000);
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else if (response.code() == 403) {
enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.authorizeError));
} else if (response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.apiNotFound));
} else {
enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Tag> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
public void onFailure(@NonNull Call<Tag> call, @NonNull Throwable t) {}
});
}
private void processNewRelease() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newReleaseTagName =
Objects.requireNonNull(binding.releaseTagName.getText()).toString();
String newReleaseTitle = Objects.requireNonNull(binding.releaseTitle.getText()).toString();
@ -220,31 +187,24 @@ public class CreateReleaseActivity extends BaseActivity {
boolean newReleaseType = binding.releaseType.isChecked();
boolean newReleaseDraft = binding.releaseDraft.isChecked();
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (newReleaseTitle.equals("")) {
Toasty.error(ctx, getString(R.string.titleErrorEmpty));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.titleErrorEmpty));
return;
}
if (newReleaseTagName.equals("")) {
Toasty.error(ctx, getString(R.string.tagNameErrorEmpty));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.tagNameErrorEmpty));
return;
}
if (checkBranch == null) {
Toasty.error(ctx, getString(R.string.selectBranchError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.selectBranchError));
return;
}
disableProcessButton();
createNewReleaseFunc(
repository.getOwner(),
repository.getName(),
@ -289,31 +249,37 @@ public class CreateReleaseActivity extends BaseActivity {
if (response.code() == 201) {
RepoDetailActivity.updateFABActions = true;
Toasty.success(ctx, getString(R.string.releaseCreatedText));
finish();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.releaseCreatedText));
new Handler().postDelayed(() -> finish(), 3000);
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else if (response.code() == 403) {
enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.authorizeError));
} else if (response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.apiNotFound));
} else {
enableProcessButton();
Toasty.error(ctx, ctx.getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Release> call, @NonNull Throwable t) {
enableProcessButton();
}
public void onFailure(@NonNull Call<Release> call, @NonNull Throwable t) {}
});
}
@ -349,7 +315,6 @@ public class CreateReleaseActivity extends BaseActivity {
branchesList);
binding.releaseBranch.setAdapter(adapter);
enableProcessButton();
binding.releaseBranch.setOnItemClickListener(
(parent, view, position, id) ->
@ -366,21 +331,6 @@ public class CreateReleaseActivity extends BaseActivity {
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
binding.createNewTag.setEnabled(false);
binding.createNewRelease.setEnabled(false);
}
private void enableProcessButton() {
binding.createNewTag.setEnabled(true);
binding.createNewRelease.setEnabled(true);
}
@Override
public void onResume() {
super.onResume();

View File

@ -1,22 +1,16 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import org.gitnex.tea4j.v2.models.CreateRepoOption;
import org.gitnex.tea4j.v2.models.Organization;
@ -26,7 +20,7 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateRepoBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import retrofit2.Call;
import retrofit2.Callback;
@ -38,103 +32,121 @@ public class CreateRepoActivity extends BaseActivity {
// https://github.com/go-gitea/gitea/blob/52cfd2743c0e85b36081cf80a850e6a5901f1865/models/repo.go#L964-L967
final List<String> reservedRepoNames = Arrays.asList(".", "..");
final Pattern reservedRepoPatterns = Pattern.compile("\\.(git|wiki)$");
public ImageView closeActivity;
List<String> organizationsList = new ArrayList<>();
private View.OnClickListener onClickListener;
private AutoCompleteTextView spinner;
private Button createRepo;
private EditText repoName;
private EditText repoDesc;
private CheckBox repoAccess;
List<String> issueLabelsList = new ArrayList<>();
List<String> licenseList = new ArrayList<>();
private ActivityCreateRepoBinding activityCreateRepoBinding;
private String loginUid;
private String selectedOwner;
private final View.OnClickListener createRepoListener = v -> processNewRepo();
private String selectedIssueLabels;
private String selectedLicense;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCreateRepoBinding activityCreateRepoBinding =
ActivityCreateRepoBinding.inflate(getLayoutInflater());
activityCreateRepoBinding = ActivityCreateRepoBinding.inflate(getLayoutInflater());
setContentView(activityCreateRepoBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(ctx);
loginUid = getAccount().getAccount().getUserName();
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
closeActivity = activityCreateRepoBinding.close;
repoName = activityCreateRepoBinding.newRepoName;
repoDesc = activityCreateRepoBinding.newRepoDescription;
repoAccess = activityCreateRepoBinding.newRepoPrivate;
repoName.requestFocus();
assert imm != null;
imm.showSoftInput(repoName, InputMethodManager.SHOW_IMPLICIT);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
spinner = activityCreateRepoBinding.ownerSpinner;
getOrganizations(loginUid);
createRepo = activityCreateRepoBinding.createNewRepoButton;
disableProcessButton();
activityCreateRepoBinding.topAppBar.setNavigationOnClickListener(v -> finish());
if (!connToInternet) {
MenuItem attachment = activityCreateRepoBinding.topAppBar.getMenu().getItem(0);
attachment.setVisible(false);
MenuItem markdown = activityCreateRepoBinding.topAppBar.getMenu().getItem(1);
markdown.setVisible(false);
disableProcessButton();
} else {
String[] licenses = getResources().getStringArray(R.array.licenses);
Collections.addAll(licenseList, licenses);
getLicenses();
createRepo.setOnClickListener(createRepoListener);
}
issueLabelsList.add(getString(R.string.advanced));
issueLabelsList.add(getString(R.string.defaultText));
getIssueLabels();
activityCreateRepoBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
if (id == R.id.create) {
processNewRepo();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
}
private void processNewRepo() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newRepoName = repoName.getText().toString();
String newRepoDesc = repoDesc.getText().toString();
boolean newRepoAccess = repoAccess.isChecked();
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
String newRepoName =
Objects.requireNonNull(activityCreateRepoBinding.newRepoName.getText()).toString();
String newRepoDesc =
Objects.requireNonNull(activityCreateRepoBinding.newRepoDescription.getText())
.toString();
boolean newRepoAccess = activityCreateRepoBinding.newRepoPrivate.isChecked();
boolean repoAsTemplate = activityCreateRepoBinding.setAsTemplate.isChecked();
String defaultBranch =
Objects.requireNonNull(activityCreateRepoBinding.defaultBranch.getText())
.toString();
if (!newRepoDesc.equals("")) {
if (newRepoDesc.length() > 255) {
Toasty.warning(ctx, getString(R.string.repoDescError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.repoDescError));
return;
}
}
if (newRepoName.equals("")) {
Toasty.error(ctx, getString(R.string.repoNameErrorEmpty));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.repoNameErrorEmpty));
} else if (!AppUtil.checkStrings(newRepoName)) {
Toasty.warning(ctx, getString(R.string.repoNameErrorInvalid));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.repoNameErrorInvalid));
} else if (reservedRepoNames.contains(newRepoName)) {
Toasty.warning(ctx, getString(R.string.repoNameErrorReservedName));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.repoNameErrorReservedName));
} else if (reservedRepoPatterns.matcher(newRepoName).find()) {
Toasty.warning(ctx, getString(R.string.repoNameErrorReservedPatterns));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.repoNameErrorReservedPatterns));
} else if (defaultBranch.equalsIgnoreCase("")) {
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.repoDefaultBranchError));
} else if (selectedOwner == null) {
Toasty.error(ctx, getString(R.string.repoOwnerError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.repoOwnerError));
} else {
disableProcessButton();
createNewRepository(loginUid, newRepoName, newRepoDesc, selectedOwner, newRepoAccess);
createNewRepository(
loginUid,
newRepoName,
newRepoDesc,
selectedOwner,
newRepoAccess,
defaultBranch,
repoAsTemplate);
}
}
@ -143,7 +155,9 @@ public class CreateRepoActivity extends BaseActivity {
String repoName,
String repoDesc,
String selectedOwner,
boolean isPrivate) {
boolean isPrivate,
String defaultBranch,
boolean repoAsTemplate) {
CreateRepoOption createRepository = new CreateRepoOption();
createRepository.setAutoInit(true);
@ -151,6 +165,10 @@ public class CreateRepoActivity extends BaseActivity {
createRepository.setPrivate(isPrivate);
createRepository.setReadme("Default");
createRepository.setName(repoName);
createRepository.setDefaultBranch(defaultBranch);
createRepository.setIssueLabels(selectedIssueLabels);
createRepository.setTemplate(repoAsTemplate);
createRepository.setLicense(selectedLicense);
Call<Repository> call;
if (selectedOwner.equals(loginUid)) {
@ -164,7 +182,7 @@ public class CreateRepoActivity extends BaseActivity {
}
call.enqueue(
new Callback<Repository>() {
new Callback<>() {
@Override
public void onResponse(
@ -175,40 +193,68 @@ public class CreateRepoActivity extends BaseActivity {
MainActivity.reloadRepos = true;
OrganizationDetailActivity.updateOrgFABActions = true;
Toasty.success(ctx, getString(R.string.repoCreated));
enableProcessButton();
finish();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.repoCreated));
new Handler().postDelayed(() -> finish(), 3000);
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else if (response.code() == 409) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.repoExistsError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.repoExistsError));
} else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Repository> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
public void onFailure(@NonNull Call<Repository> call, @NonNull Throwable t) {}
});
}
private void getIssueLabels() {
ArrayAdapter<String> adapter =
new ArrayAdapter<>(
CreateRepoActivity.this, R.layout.list_spinner_items, issueLabelsList);
activityCreateRepoBinding.issueLabels.setAdapter(adapter);
activityCreateRepoBinding.issueLabels.setOnItemClickListener(
(parent, view, position, id) ->
selectedIssueLabels = issueLabelsList.get(position));
}
private void getLicenses() {
ArrayAdapter<String> adapter =
new ArrayAdapter<>(
CreateRepoActivity.this, R.layout.list_spinner_items, licenseList);
activityCreateRepoBinding.licenses.setAdapter(adapter);
activityCreateRepoBinding.licenses.setOnItemClickListener(
(parent, view, position, id) -> selectedLicense = licenseList.get(position));
}
private void getOrganizations(final String userLogin) {
Call<List<Organization>> call =
RetrofitClient.getApiInterface(ctx).orgListCurrentUserOrgs(1, 50);
call.enqueue(
new Callback<List<Organization>>() {
new Callback<>() {
@Override
public void onResponse(
@ -247,9 +293,9 @@ public class CreateRepoActivity extends BaseActivity {
R.layout.list_spinner_items,
organizationsList);
spinner.setAdapter(adapter);
activityCreateRepoBinding.ownerSpinner.setAdapter(adapter);
spinner.setOnItemClickListener(
activityCreateRepoBinding.ownerSpinner.setOnItemClickListener(
(parent, view, position, id) ->
selectedOwner = organizationsList.get(position));
@ -260,7 +306,7 @@ public class CreateRepoActivity extends BaseActivity {
new Handler(Looper.getMainLooper())
.postDelayed(
() -> {
spinner.setText(
activityCreateRepoBinding.ownerSpinner.setText(
organizationsList.get(selectOwnerById),
false);
selectedOwner =
@ -270,36 +316,15 @@ public class CreateRepoActivity extends BaseActivity {
getIntent().removeExtra("organizationAction");
}
enableProcessButton();
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
}
}
@Override
public void onFailure(
@NonNull Call<List<Organization>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
@NonNull Call<List<Organization>> call, @NonNull Throwable t) {}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void disableProcessButton() {
createRepo.setEnabled(false);
}
private void enableProcessButton() {
createRepo.setEnabled(true);
}
}

View File

@ -1,20 +1,15 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.util.Log;
import android.os.Handler;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import org.gitnex.tea4j.v2.models.CreateTeamOption;
import org.gitnex.tea4j.v2.models.Team;
import org.mian.gitnex.R;
@ -23,26 +18,17 @@ import org.mian.gitnex.databinding.ActivityCreateTeamByOrgBinding;
import org.mian.gitnex.fragments.OrganizationTeamsFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import retrofit2.Call;
import retrofit2.Callback;
/**
* @author M M Arif
*/
public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClickListener {
public class CreateTeamByOrgActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private TextView teamName;
private TextView teamDesc;
private TextView teamPermission;
private TextView teamPermissionDetail;
private TextView teamAccessControls;
private TextView teamAccessControlsArray;
private Button createTeamButton;
private final String[] permissionList = {"Read", "Write", "Admin"};
public int permissionSelectedChoice = -1;
private final String[] accessControlsList =
new String[] {
"Code",
@ -53,8 +39,8 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
"External Wiki",
"External Issues"
};
private List<String> pushAccessList;
private ActivityCreateTeamByOrgBinding activityCreateTeamByOrgBinding;
private final boolean[] selectedAccessControlsTrueFalse =
new boolean[] {false, false, false, false, false, false, false};
@ -64,32 +50,18 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
super.onCreate(savedInstanceState);
ActivityCreateTeamByOrgBinding activityCreateTeamByOrgBinding =
activityCreateTeamByOrgBinding =
ActivityCreateTeamByOrgBinding.inflate(getLayoutInflater());
setContentView(activityCreateTeamByOrgBinding.getRoot());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
MenuItem attachment = activityCreateTeamByOrgBinding.topAppBar.getMenu().getItem(0);
MenuItem markdown = activityCreateTeamByOrgBinding.topAppBar.getMenu().getItem(1);
attachment.setVisible(false);
markdown.setVisible(false);
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
activityCreateTeamByOrgBinding.topAppBar.setNavigationOnClickListener(v -> finish());
ImageView closeActivity = activityCreateTeamByOrgBinding.close;
teamName = activityCreateTeamByOrgBinding.teamName;
teamDesc = activityCreateTeamByOrgBinding.teamDesc;
teamPermission = activityCreateTeamByOrgBinding.teamPermission;
teamPermissionDetail = activityCreateTeamByOrgBinding.teamPermissionDetail;
teamAccessControls = activityCreateTeamByOrgBinding.teamAccessControls;
teamAccessControlsArray = activityCreateTeamByOrgBinding.teamAccessControlsArray;
createTeamButton = activityCreateTeamByOrgBinding.createTeamButton;
teamName.requestFocus();
assert imm != null;
imm.showSoftInput(teamName, InputMethodManager.SHOW_IMPLICIT);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
teamPermission.setOnClickListener(
activityCreateTeamByOrgBinding.teamPermission.setOnClickListener(
view -> {
MaterialAlertDialogBuilder materialAlertDialogBuilderPerm =
new MaterialAlertDialogBuilder(ctx)
@ -100,29 +72,37 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
permissionSelectedChoice,
(dialogInterface, i) -> {
permissionSelectedChoice = i;
teamPermission.setText(permissionList[i]);
activityCreateTeamByOrgBinding.teamPermission
.setText(permissionList[i]);
switch (permissionList[i]) {
case "Read":
teamPermissionDetail.setVisibility(
activityCreateTeamByOrgBinding
.teamPermissionDetail.setVisibility(
View.VISIBLE);
teamPermissionDetail.setText(
activityCreateTeamByOrgBinding
.teamPermissionDetail.setText(
R.string.newTeamPermissionRead);
break;
case "Write":
teamPermissionDetail.setVisibility(
activityCreateTeamByOrgBinding
.teamPermissionDetail.setVisibility(
View.VISIBLE);
teamPermissionDetail.setText(
activityCreateTeamByOrgBinding
.teamPermissionDetail.setText(
R.string.newTeamPermissionWrite);
break;
case "Admin":
teamPermissionDetail.setVisibility(
activityCreateTeamByOrgBinding
.teamPermissionDetail.setVisibility(
View.VISIBLE);
teamPermissionDetail.setText(
activityCreateTeamByOrgBinding
.teamPermissionDetail.setText(
R.string.newTeamPermissionAdmin);
break;
default:
teamPermissionDetail.setVisibility(
activityCreateTeamByOrgBinding
.teamPermissionDetail.setVisibility(
View.GONE);
break;
}
@ -133,10 +113,10 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
materialAlertDialogBuilderPerm.create().show();
});
teamAccessControls.setOnClickListener(
activityCreateTeamByOrgBinding.teamAccessControls.setOnClickListener(
v -> {
teamAccessControls.setText("");
teamAccessControlsArray.setText("");
activityCreateTeamByOrgBinding.teamAccessControls.setText("");
activityCreateTeamByOrgBinding.teamAccessControlsArray.setText("");
pushAccessList = Arrays.asList(accessControlsList);
MaterialAlertDialogBuilder materialAlertDialogBuilder =
@ -181,19 +161,23 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
if (value) {
teamAccessControls.setText(
activityCreateTeamByOrgBinding
.teamAccessControls.setText(
getString(
R.string
.newTeamPermissionValues,
teamAccessControls
activityCreateTeamByOrgBinding
.teamAccessControls
.getText(),
pushAccessList.get(
selectedVal)));
teamAccessControlsArray.setText(
activityCreateTeamByOrgBinding
.teamAccessControlsArray.setText(
getString(
R.string
.newTeamPermissionValuesFinal,
teamAccessControlsArray
activityCreateTeamByOrgBinding
.teamAccessControlsArray
.getText(),
repoCode));
}
@ -203,20 +187,26 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
String data =
String.valueOf(
teamAccessControls.getText());
activityCreateTeamByOrgBinding
.teamAccessControls
.getText());
if (!data.equals("")) {
teamAccessControls.setText(
activityCreateTeamByOrgBinding
.teamAccessControls.setText(
data.substring(0, data.length() - 2));
}
String dataArray =
String.valueOf(
teamAccessControlsArray.getText());
activityCreateTeamByOrgBinding
.teamAccessControlsArray
.getText());
if (!dataArray.equals("")) {
teamAccessControlsArray.setText(
activityCreateTeamByOrgBinding
.teamAccessControlsArray.setText(
dataArray.substring(
0, dataArray.length() - 2));
}
@ -225,47 +215,47 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
materialAlertDialogBuilder.create().show();
});
createTeamButton.setEnabled(false);
activityCreateTeamByOrgBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
if (!connToInternet) {
createTeamButton.setEnabled(false);
GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius(8);
shape.setColor(ResourcesCompat.getColor(getResources(), R.color.hintColor, null));
createTeamButton.setBackground(shape);
} else {
createTeamButton.setEnabled(true);
createTeamButton.setOnClickListener(this);
}
if (id == R.id.create) {
processCreateTeam();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
}
private void processCreateTeam() {
final String orgName = getIntent().getStringExtra("orgName");
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String newTeamName = teamName.getText().toString();
String newTeamDesc = teamDesc.getText().toString();
String newTeamPermission = teamPermission.getText().toString().toLowerCase();
String newTeamAccessControls = teamAccessControlsArray.getText().toString();
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
String newTeamName =
Objects.requireNonNull(activityCreateTeamByOrgBinding.teamName.getText())
.toString();
String newTeamDesc =
Objects.requireNonNull(activityCreateTeamByOrgBinding.teamDesc.getText())
.toString();
String newTeamPermission =
Objects.requireNonNull(activityCreateTeamByOrgBinding.teamPermission.getText())
.toString()
.toLowerCase();
String newTeamAccessControls =
activityCreateTeamByOrgBinding.teamAccessControlsArray.getText().toString();
if (newTeamName.equals("")) {
Toasty.error(ctx, getString(R.string.teamNameEmpty));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.teamNameEmpty));
return;
}
if (!AppUtil.checkStringsWithAlphaNumericDashDotUnderscore(newTeamName)) {
Toasty.warning(ctx, getString(R.string.teamNameError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.teamNameError));
return;
}
@ -273,20 +263,25 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
if (!AppUtil.checkStrings(newTeamDesc)) {
Toasty.warning(ctx, getString(R.string.teamDescError));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.teamDescError));
return;
}
if (newTeamDesc.length() > 100) {
Toasty.warning(ctx, getString(R.string.teamDescLimit));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.teamDescLimit));
return;
}
}
if (newTeamPermission.equals("")) {
Toasty.error(ctx, getString(R.string.teamPermissionEmpty));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.teamPermissionEmpty));
return;
}
@ -329,7 +324,7 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
RetrofitClient.getApiInterface(ctx).orgCreateTeam(orgName, createNewTeamJson);
call3.enqueue(
new Callback<Team>() {
new Callback<>() {
@Override
public void onResponse(
@ -341,39 +336,32 @@ public class CreateTeamByOrgActivity extends BaseActivity implements View.OnClic
OrganizationTeamsFragment.resumeTeams = true;
Toasty.success(ctx, getString(R.string.teamCreated));
finish();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.teamCreated));
new Handler().postDelayed(() -> finish(), 3000);
}
} else if (response2.code() == 404) {
Toasty.warning(ctx, getString(R.string.apiNotFound));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.apiNotFound));
} else if (response2.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else {
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Team> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
public void onFailure(@NonNull Call<Team> call, @NonNull Throwable t) {}
});
}
@Override
public void onClick(View v) {
if (v == createTeamButton) {
processCreateTeam();
}
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -1,22 +1,18 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.google.android.material.datepicker.MaterialDatePicker;
import com.vdurmont.emoji.EmojiParser;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@ -25,7 +21,9 @@ import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;
import org.gitnex.tea4j.v2.models.EditIssueOption;
import org.gitnex.tea4j.v2.models.Issue;
import org.gitnex.tea4j.v2.models.Milestone;
@ -35,10 +33,9 @@ import org.mian.gitnex.databinding.ActivityEditIssueBinding;
import org.mian.gitnex.fragments.IssuesFragment;
import org.mian.gitnex.fragments.PullRequestsFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.contexts.IssueContext;
import retrofit2.Call;
import retrofit2.Callback;
@ -46,15 +43,12 @@ import retrofit2.Callback;
/**
* @author M M Arif
*/
public class EditIssueActivity extends BaseActivity implements View.OnClickListener {
public class EditIssueActivity extends BaseActivity {
private ActivityEditIssueBinding binding;
private final String msState = "open";
private final LinkedHashMap<String, Milestone> milestonesList = new LinkedHashMap<>();
private View.OnClickListener onClickListener;
private int resultLimit;
private int milestoneId = 0;
private Date currentDate = null;
private IssueContext issue;
private boolean renderMd = false;
@ -66,17 +60,16 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
binding = ActivityEditIssueBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
resultLimit = Constants.getCurrentResultLimit(ctx);
int resultLimit = Constants.getCurrentResultLimit(ctx);
issue = IssueContext.fromIntent(getIntent());
binding.editIssueTitle.requestFocus();
assert imm != null;
imm.showSoftInput(binding.editIssueTitle, InputMethodManager.SHOW_IMPLICIT);
binding.topAppBar.setNavigationOnClickListener(v -> finish());
MenuItem attachment = binding.topAppBar.getMenu().getItem(0);
MenuItem create = binding.topAppBar.getMenu().getItem(2);
attachment.setVisible(false);
create.setTitle(getString(R.string.menuEditText));
binding.editIssueDescription.setOnTouchListener(
(touchView, motionEvent) -> {
@ -90,23 +83,51 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
return false;
});
initCloseListener();
binding.close.setOnClickListener(onClickListener);
binding.editIssueDueDate.setOnClickListener(this);
binding.editIssueButton.setOnClickListener(this);
if (issue.getIssueType().equalsIgnoreCase("Pull")) {
binding.toolbarTitle.setText(
binding.topAppBar.setTitle(
getString(R.string.editPrNavHeader, String.valueOf(issue.getIssueIndex())));
} else {
binding.toolbarTitle.setText(
binding.topAppBar.setTitle(
getString(R.string.editIssueNavHeader, String.valueOf(issue.getIssueIndex())));
}
disableProcessButton();
showDatePickerDialog();
binding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
if (id == R.id.markdown) {
if (!renderMd) {
Markdown.render(
ctx,
EmojiParser.parseToUnicode(
Objects.requireNonNull(
binding.editIssueDescription.getText())
.toString()),
binding.markdownPreview,
issue.getRepository());
binding.markdownPreview.setVisibility(View.VISIBLE);
binding.editIssueDescriptionLayout.setVisibility(View.GONE);
renderMd = true;
} else {
binding.markdownPreview.setVisibility(View.GONE);
binding.editIssueDescriptionLayout.setVisibility(View.VISIBLE);
renderMd = false;
}
return true;
} else if (id == R.id.create) {
processEditIssue();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
getIssue(
issue.getRepository().getOwner(),
issue.getRepository().getName(),
@ -119,81 +140,29 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
}
}
private void initCloseListener() {
onClickListener = view -> finish();
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.markdown_switcher, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.markdown) {
if (!renderMd) {
Markdown.render(
ctx,
EmojiParser.parseToUnicode(
Objects.requireNonNull(binding.editIssueDescription.getText())
.toString()),
binding.markdownPreview,
issue.getRepository());
binding.markdownPreview.setVisibility(View.VISIBLE);
binding.editIssueDescriptionLayout.setVisibility(View.GONE);
renderMd = true;
} else {
binding.markdownPreview.setVisibility(View.GONE);
binding.editIssueDescriptionLayout.setVisibility(View.VISIBLE);
renderMd = false;
}
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
private void processEditIssue() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
String editIssueTitleForm =
Objects.requireNonNull(binding.editIssueTitle.getText()).toString();
String editIssueDescriptionForm =
Objects.requireNonNull(binding.editIssueDescription.getText()).toString();
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
String dueDate = Objects.requireNonNull(binding.editIssueDueDate.getText()).toString();
if (editIssueTitleForm.equals("")) {
Toasty.error(ctx, getString(R.string.issueTitleEmpty));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.issueTitleEmpty));
return;
}
disableProcessButton();
editIssue(
issue.getRepository().getOwner(),
issue.getRepository().getName(),
issue.getIssueIndex(),
editIssueTitleForm,
editIssueDescriptionForm,
milestoneId);
milestoneId,
dueDate);
}
private void editIssue(
@ -202,12 +171,21 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
int issueIndex,
String title,
String description,
int milestoneId) {
int milestoneId,
String dueDate) {
EditIssueOption issueData = new EditIssueOption();
issueData.setTitle(title);
issueData.setBody(description);
issueData.setDueDate(currentDate);
String[] date = dueDate.split("-");
if (!dueDate.equalsIgnoreCase("")) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Integer.parseInt(date[0]));
calendar.set(Calendar.MONTH, Integer.parseInt(date[1]));
calendar.set(Calendar.DATE, Integer.parseInt(date[2]));
Date dueDate_ = calendar.getTime();
issueData.setDueDate(dueDate_);
}
issueData.setMilestone((long) milestoneId);
Call<Issue> call =
@ -215,7 +193,7 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
.issueEditIssue(repoOwner, repoName, (long) issueIndex, issueData);
call.enqueue(
new Callback<Issue>() {
new Callback<>() {
@Override
public void onResponse(
@ -226,10 +204,16 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
if (issue.getIssueType().equalsIgnoreCase("Pull")) {
Toasty.success(ctx, getString(R.string.editPrSuccessMessage));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.editPrSuccessMessage));
} else {
Toasty.success(ctx, getString(R.string.editIssueSuccessMessage));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.editIssueSuccessMessage));
}
Intent result = new Intent();
@ -238,57 +222,44 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
PullRequestsFragment.resumePullRequests =
issue.getIssue().getPullRequest() != null;
setResult(200, result);
finish();
new Handler().postDelayed(() -> finish(), 3000);
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Issue> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
enableProcessButton();
}
public void onFailure(@NonNull Call<Issue> call, @NonNull Throwable t) {}
});
}
@Override
public void onClick(View v) {
private void showDatePickerDialog() {
if (v == binding.editIssueDueDate) {
MaterialDatePicker.Builder<Long> builder = MaterialDatePicker.Builder.datePicker();
builder.setSelection(Calendar.getInstance().getTimeInMillis());
builder.setTitleText(R.string.newIssueDueDateTitle);
MaterialDatePicker<Long> materialDatePicker = builder.build();
final Calendar c = Calendar.getInstance();
int mYear = c.get(Calendar.YEAR);
final int mMonth = c.get(Calendar.MONTH);
final int mDay = c.get(Calendar.DAY_OF_MONTH);
binding.editIssueDueDate.setOnClickListener(
v -> materialDatePicker.show(getSupportFragmentManager(), "DATE_PICKER"));
DatePickerDialog datePickerDialog =
new DatePickerDialog(
this,
(view, year, monthOfYear, dayOfMonth) -> {
binding.editIssueDueDate.setText(
getString(
R.string.setDueDate,
year,
(monthOfYear + 1),
dayOfMonth));
currentDate = new Date(year - 1900, monthOfYear, dayOfMonth);
},
mYear,
mMonth,
mDay);
datePickerDialog.show();
} else if (v == binding.editIssueButton) {
processEditIssue();
}
materialDatePicker.addOnPositiveButtonClickListener(
selection -> {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.setTimeInMillis(selection);
SimpleDateFormat format =
new SimpleDateFormat(
"yyyy-MM-dd", new Locale(tinyDB.getString("locale")));
String formattedDate = format.format(calendar.getTime());
binding.editIssueDueDate.setText(formattedDate);
});
}
private void getIssue(
@ -431,8 +402,6 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
}
},
500);
enableProcessButton();
}
}
@ -454,35 +423,27 @@ public class EditIssueActivity extends BaseActivity implements View.OnClickListe
String dueDate = formatter.format(response.body().getDueDate());
binding.editIssueDueDate.setText(dueDate);
}
// enableProcessButton();
} else if (response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else {
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Issue> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
// Log.e("onFailure", t.toString());
}
});
}
private void disableProcessButton() {
binding.editIssueButton.setEnabled(false);
}
private void enableProcessButton() {
binding.editIssueButton.setEnabled(true);
}
@Override
public void onResume() {
super.onResume();

View File

@ -21,6 +21,7 @@ import com.vdurmont.emoji.EmojiParser;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Objects;
import okhttp3.ResponseBody;
import org.apache.commons.io.FilenameUtils;
import org.gitnex.tea4j.v2.models.ContentsResponse;
@ -60,7 +61,9 @@ public class FileViewActivity extends BaseActivity implements BottomSheetListene
OutputStream outputStream =
getContentResolver()
.openOutputStream(result.getData().getData());
.openOutputStream(
Objects.requireNonNull(
result.getData().getData()));
NotificationCompat.Builder builder =
new NotificationCompat.Builder(ctx, ctx.getPackageName())
@ -108,6 +111,17 @@ public class FileViewActivity extends BaseActivity implements BottomSheetListene
assert response.body() != null;
builder.setOngoing(false)
.setContentTitle(
getString(
R.string
.fileViewerNotificationTitleFinished))
.setContentText(
getString(
R.string
.fileViewerNotificationDescriptionFinished,
file.getName()));
AppUtil.copyProgress(
response.body().byteStream(),
outputStream,
@ -120,19 +134,10 @@ public class FileViewActivity extends BaseActivity implements BottomSheetListene
builder.build());
});
builder.setContentTitle(
getString(
R.string
.fileViewerNotificationTitleFinished))
.setContentText(
getString(
R.string
.fileViewerNotificationDescriptionFinished,
file.getName()));
} catch (IOException ignored) {
builder.setContentTitle(
builder.setOngoing(false)
.setContentTitle(
getString(
R.string
.fileViewerNotificationTitleFailed))

View File

@ -1,5 +1,8 @@
package org.mian.gitnex.activities;
import android.app.Activity;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Color;
@ -21,22 +24,30 @@ import android.widget.ScrollView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.text.HtmlCompat;
import androidx.core.widget.ImageViewCompat;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.amulyakhare.textdrawable.TextDrawable;
import com.google.android.material.card.MaterialCardView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.vdurmont.emoji.EmojiParser;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import okhttp3.ResponseBody;
import org.apache.commons.io.FilenameUtils;
import org.gitnex.tea4j.v2.models.Attachment;
import org.gitnex.tea4j.v2.models.EditIssueOption;
import org.gitnex.tea4j.v2.models.Issue;
import org.gitnex.tea4j.v2.models.IssueLabelsOption;
@ -55,6 +66,7 @@ import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityIssueDetailBinding;
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
import org.mian.gitnex.databinding.CustomImageViewDialogBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.databinding.CustomPrInfoDialogBinding;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
@ -64,12 +76,14 @@ import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.LabelWidthCalculator;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.contexts.IssueContext;
import org.mian.gitnex.notifications.Notifications;
import org.mian.gitnex.structs.BottomSheetListener;
import org.mian.gitnex.viewmodels.IssueCommentsViewModel;
import org.mian.gitnex.views.ReactionList;
@ -110,6 +124,13 @@ public class IssueDetailActivity extends BaseActivity
private boolean loadingFinishedIssue = false;
private boolean loadingFinishedPr = false;
private boolean loadingFinishedRepo = false;
private String filename;
private Long filesize;
private String filehash;
private String instanceUrlOnly;
private String token;
private int page = 1;
public ActivityResultLauncher<Intent> editIssueLauncher =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
@ -129,7 +150,116 @@ public class IssueDetailActivity extends BaseActivity
}
}
});
private int page = 1;
public ActivityResultLauncher<Intent> downloadAttachmentLauncher =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
assert result.getData() != null;
try {
OutputStream outputStream =
getContentResolver()
.openOutputStream(
Objects.requireNonNull(
result.getData().getData()));
NotificationCompat.Builder builder =
new NotificationCompat.Builder(ctx, ctx.getPackageName())
.setContentTitle(
getString(
R.string
.fileViewerNotificationTitleStarted))
.setContentText(
getString(
R.string
.fileViewerNotificationDescriptionStarted,
filename))
.setSmallIcon(R.drawable.gitnex_transparent)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setChannelId(
Constants.downloadNotificationChannelId)
.setProgress(100, 0, false)
.setOngoing(true);
int notificationId = Notifications.uniqueNotificationId(ctx);
NotificationManager notificationManager =
(NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, builder.build());
Thread thread =
new Thread(
() -> {
try {
Call<ResponseBody> call =
RetrofitClient.getWebInterface(
ctx,
instanceUrlOnly)
.getAttachment(filehash);
Response<ResponseBody> response =
call.execute();
assert response.body() != null;
builder.setOngoing(false)
.setContentTitle(
getString(
R.string
.fileViewerNotificationTitleFinished))
.setContentText(
getString(
R.string
.fileViewerNotificationDescriptionFinished,
filename));
AppUtil.copyProgress(
response.body().byteStream(),
outputStream,
filesize,
progress -> {
builder.setProgress(
100, progress, false);
notificationManager.notify(
notificationId,
builder.build());
});
} catch (IOException ignored) {
builder.setOngoing(false)
.setContentTitle(
getString(
R.string
.fileViewerNotificationTitleFailed))
.setContentText(
getString(
R.string
.fileViewerNotificationDescriptionFailed,
filename));
} finally {
builder.setProgress(0, 0, false)
.setOngoing(false);
notificationManager.notify(
notificationId, builder.build());
}
});
thread.start();
} catch (IOException ignored) {
}
}
});
@Override
public void onCreate(Bundle savedInstanceState) {
@ -148,6 +278,11 @@ public class IssueDetailActivity extends BaseActivity
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
String instanceUrl = ((BaseActivity) ctx).getAccount().getAccount().getInstanceUrl();
instanceUrlOnly = instanceUrl.substring(0, instanceUrl.lastIndexOf("api/v1/"));
token = ((BaseActivity) ctx).getAccount().getAccount().getToken();
materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx, R.style.ThemeOverlay_Material3_Dialog_Alert);
@ -191,10 +326,11 @@ public class IssueDetailActivity extends BaseActivity
viewBinding.toolbarTitle.setText(repoName);
getSingleIssue(repoOwner, repoName, issueIndex);
getAttachments();
fetchDataAsync(repoOwner, repoName, issueIndex);
if (getIntent().getStringExtra("openPrDiff") != null
&& getIntent().getStringExtra("openPrDiff").equals("true")) {
&& Objects.equals(getIntent().getStringExtra("openPrDiff"), "true")) {
startActivity(issue.getIntent(ctx, DiffActivity.class));
}
}
@ -456,7 +592,7 @@ public class IssueDetailActivity extends BaseActivity
if (issue.hasIssue()
&& getIntent().getStringExtra("openedFromLink") != null
&& getIntent().getStringExtra("openedFromLink").equals("true")) {
&& Objects.equals(getIntent().getStringExtra("openedFromLink"), "true")) {
Intent intent = issue.getRepository().getIntent(ctx, RepoDetailActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
@ -624,7 +760,6 @@ public class IssueDetailActivity extends BaseActivity
} else if (response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else if (response.code() == 404) {
Toasty.warning(ctx, getResources().getString(R.string.noDataFound));
@ -636,7 +771,6 @@ public class IssueDetailActivity extends BaseActivity
public void onFailure(@NonNull Call<Issue> call, @NonNull Throwable t) {
viewBinding.progressBar.setVisibility(View.GONE);
Log.e("onFailure", t.toString());
}
});
@ -1104,4 +1238,135 @@ public class IssueDetailActivity extends BaseActivity
}
});
}
private void getAttachments() {
Call<List<Attachment>> call =
RetrofitClient.getApiInterface(ctx)
.issueListIssueAttachments(
issue.getRepository().getOwner(),
issue.getRepository().getName(),
(long) issueIndex);
call.enqueue(
new Callback<>() {
@Override
public void onResponse(
@NonNull Call<List<Attachment>> call,
@NonNull retrofit2.Response<List<Attachment>> response) {
List<Attachment> attachment = response.body();
if (response.code() == 200) {
assert attachment != null;
if (attachment.size() > 0) {
viewBinding.attachmentFrame.setVisibility(View.VISIBLE);
LinearLayout.LayoutParams paramsAttachment =
new LinearLayout.LayoutParams(96, 96);
paramsAttachment.setMargins(0, 0, 48, 0);
for (int i = 0; i < attachment.size(); i++) {
ImageView attachmentView = new ImageView(ctx);
MaterialCardView materialCardView = new MaterialCardView(ctx);
materialCardView.setLayoutParams(paramsAttachment);
materialCardView.setStrokeWidth(0);
materialCardView.setCardBackgroundColor(Color.TRANSPARENT);
if (Arrays.asList(
"bmp", "gif", "jpg", "jpeg", "png", "webp",
"heic", "heif")
.contains(
FilenameUtils.getExtension(
attachment.get(i).getName())
.toLowerCase())) {
PicassoService.getInstance(ctx)
.get()
.load(
attachment.get(i).getBrowserDownloadUrl()
+ "?token="
+ token)
.placeholder(R.drawable.loader_animated)
.resize(120, 120)
.centerCrop()
.error(R.drawable.ic_close)
.into(attachmentView);
viewBinding.attachmentsView.addView(materialCardView);
attachmentView.setLayoutParams(paramsAttachment);
materialCardView.addView(attachmentView);
int finalI1 = i;
materialCardView.setOnClickListener(
v1 ->
imageViewDialog(
attachment
.get(finalI1)
.getBrowserDownloadUrl()));
} else {
attachmentView.setImageResource(
R.drawable.ic_file_download);
attachmentView.setPadding(4, 4, 4, 4);
viewBinding.attachmentsView.addView(materialCardView);
attachmentView.setLayoutParams(paramsAttachment);
materialCardView.addView(attachmentView);
int finalI = i;
materialCardView.setOnClickListener(
v1 -> {
filesize = attachment.get(finalI).getSize();
filename = attachment.get(finalI).getName();
filehash = attachment.get(finalI).getUuid();
requestFileDownload();
});
}
}
} else {
viewBinding.attachmentFrame.setVisibility(View.GONE);
}
}
}
@Override
public void onFailure(
@NonNull Call<List<Attachment>> call, @NonNull Throwable t) {}
});
}
private void requestFileDownload() {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_TITLE, filename);
intent.setType("*/*");
downloadAttachmentLauncher.launch(intent);
}
private void imageViewDialog(String url) {
CustomImageViewDialogBinding imageViewDialogBinding =
CustomImageViewDialogBinding.inflate(LayoutInflater.from(ctx));
View view = imageViewDialogBinding.getRoot();
materialAlertDialogBuilder.setView(view);
materialAlertDialogBuilder.setNeutralButton(getString(R.string.close), null);
PicassoService.getInstance(ctx)
.get()
.load(url + "?token=" + token)
.placeholder(R.drawable.loader_animated)
.resize(0, 1600)
.onlyScaleDown()
.centerCrop()
.error(R.drawable.ic_close)
.into(imageViewDialogBinding.imageView);
materialAlertDialogBuilder.create().show();
}
}

View File

@ -30,7 +30,7 @@ import org.mian.gitnex.databinding.ActivityLoginBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.NetworkStatusObserver;
import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.structs.Protocol;
@ -88,7 +88,10 @@ public class LoginActivity extends BaseActivity {
selectedProtocol = String.valueOf(parent.getItemAtPosition(position));
if (selectedProtocol.equals(String.valueOf(Protocol.HTTP))) {
Toasty.warning(ctx, getResources().getString(R.string.protocolError));
SnackBar.warning(
ctx,
findViewById(android.R.id.content),
getString(R.string.protocolError));
}
});
@ -137,10 +140,10 @@ public class LoginActivity extends BaseActivity {
disableProcessButton();
loginButton.setText(
getResources().getString(R.string.btnLogin));
Toasty.error(
SnackBar.error(
ctx,
getResources()
.getString(R.string.checkNetConnection));
findViewById(android.R.id.content),
getString(R.string.checkNetConnection));
}
}));
@ -159,7 +162,10 @@ public class LoginActivity extends BaseActivity {
if (selectedProtocol == null) {
Toasty.error(ctx, getResources().getString(R.string.protocolEmptyError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.protocolEmptyError));
enableProcessButton();
return;
}
@ -197,7 +203,8 @@ public class LoginActivity extends BaseActivity {
if (instanceUrlET.getText().toString().equals("")) {
Toasty.error(ctx, getResources().getString(R.string.emptyFieldURL));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.emptyFieldURL));
enableProcessButton();
return;
}
@ -206,19 +213,28 @@ public class LoginActivity extends BaseActivity {
if (otpCode.length() != 0 && otpCode.length() != 6) {
Toasty.warning(ctx, getResources().getString(R.string.loginOTPTypeError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.loginOTPTypeError));
enableProcessButton();
return;
}
if (loginUid.equals("")) {
Toasty.error(ctx, getResources().getString(R.string.emptyFieldUsername));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.emptyFieldUsername));
enableProcessButton();
return;
}
if (loginPass.equals("")) {
Toasty.error(ctx, getResources().getString(R.string.emptyFieldPassword));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.emptyFieldPassword));
enableProcessButton();
return;
}
@ -234,7 +250,10 @@ public class LoginActivity extends BaseActivity {
if (loginToken.equals("")) {
Toasty.error(ctx, getResources().getString(R.string.loginTokenError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.loginTokenError));
enableProcessButton();
return;
}
@ -245,7 +264,8 @@ public class LoginActivity extends BaseActivity {
} catch (Exception e) {
Toasty.error(ctx, getResources().getString(R.string.malformedUrl));
SnackBar.error(
ctx, findViewById(android.R.id.content), getString(R.string.malformedUrl));
enableProcessButton();
}
}
@ -331,8 +351,10 @@ public class LoginActivity extends BaseActivity {
if (!Version.valid(version.getVersion())) {
Toasty.error(
ctx, getResources().getString(R.string.versionUnknown));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.versionUnknown));
enableProcessButton();
return;
}
@ -376,9 +398,10 @@ public class LoginActivity extends BaseActivity {
login(loginType, loginUid, loginPass, loginOTP, loginToken);
} else {
Toasty.warning(
SnackBar.warning(
ctx,
getResources().getString(R.string.versionUnsupportedNew));
findViewById(android.R.id.content),
getString(R.string.versionUnsupportedNew));
login(loginType, loginUid, loginPass, loginOTP, loginToken);
}
@ -412,8 +435,10 @@ public class LoginActivity extends BaseActivity {
public void onFailure(
@NonNull Call<ServerVersion> callVersion, @NonNull Throwable t) {
Toasty.error(
ctx, getResources().getString(R.string.genericServerResponseError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
enableProcessButton();
}
});
@ -475,17 +500,17 @@ public class LoginActivity extends BaseActivity {
finish();
break;
case 401:
Toasty.error(
SnackBar.error(
ctx,
getResources().getString(R.string.unauthorizedApiError));
findViewById(android.R.id.content),
getString(R.string.unauthorizedApiError));
enableProcessButton();
break;
default:
Toasty.error(
SnackBar.error(
ctx,
getResources()
.getString(
R.string.genericApiError, response.code()));
findViewById(android.R.id.content),
getString(R.string.genericApiError, response.code()));
enableProcessButton();
}
}
@ -493,7 +518,10 @@ public class LoginActivity extends BaseActivity {
@Override
public void onFailure(@NonNull Call<User> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
enableProcessButton();
}
});
@ -580,13 +608,12 @@ public class LoginActivity extends BaseActivity {
tokenName);
} else {
Toasty.error(
SnackBar.error(
ctx,
getResources()
.getString(
R.string
.genericApiError,
response.code()));
findViewById(android.R.id.content),
getString(
R.string.genericApiError,
response.code()));
enableProcessButton();
}
}
@ -596,12 +623,10 @@ public class LoginActivity extends BaseActivity {
@NonNull Call<Void> delToken,
@NonNull Throwable t) {
Toasty.error(
SnackBar.error(
ctx,
getResources()
.getString(
R.string
.malformedJson));
findViewById(android.R.id.content),
getString(R.string.malformedJson));
enableProcessButton();
}
});
@ -612,10 +637,10 @@ public class LoginActivity extends BaseActivity {
setupToken(loginUid, loginPass, loginOTP, tokenName);
} else {
Toasty.error(
SnackBar.error(
ctx,
getResources()
.getString(R.string.genericApiError, response.code()));
findViewById(android.R.id.content),
getString(R.string.genericApiError, response.code()));
enableProcessButton();
}
}
@ -624,7 +649,10 @@ public class LoginActivity extends BaseActivity {
public void onFailure(
@NonNull Call<List<AccessToken>> call, @NonNull Throwable t) {
Toasty.error(ctx, getResources().getString(R.string.malformedJson));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.malformedJson));
enableProcessButton();
}
});
@ -750,22 +778,21 @@ public class LoginActivity extends BaseActivity {
finish();
break;
case 401:
Toasty.error(
SnackBar.error(
ctx,
getResources()
.getString(
R.string
.unauthorizedApiError));
findViewById(android.R.id.content),
getString(
R.string
.unauthorizedApiError));
enableProcessButton();
break;
default:
Toasty.error(
SnackBar.error(
ctx,
getResources()
.getString(
R.string
.genericApiError,
response.code()));
findViewById(android.R.id.content),
getString(
R.string.genericApiError,
response.code()));
enableProcessButton();
}
}
@ -775,22 +802,20 @@ public class LoginActivity extends BaseActivity {
@NonNull Call<User> call,
@NonNull Throwable t) {
Toasty.error(
SnackBar.error(
ctx,
getResources()
.getString(R.string.genericError));
findViewById(android.R.id.content),
getString(R.string.genericError));
enableProcessButton();
}
});
}
} else if (responseCreate.code() == 500) {
Toasty.error(
SnackBar.error(
ctx,
getResources()
.getString(
R.string.genericApiError,
responseCreate.code()));
findViewById(android.R.id.content),
getString(R.string.genericApiError, responseCreate.code()));
enableProcessButton();
}
}
@ -799,7 +824,10 @@ public class LoginActivity extends BaseActivity {
public void onFailure(
@NonNull Call<AccessToken> createUserToken, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericServerResponseError));
}
});
}

View File

@ -553,7 +553,6 @@ public class MainActivity extends BaseActivity
giteaVersion();
serverPageLimitSettings();
noConnection = false;
}
},
1500);

View File

@ -1,11 +1,11 @@
package org.mian.gitnex.activities;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import java.util.ArrayList;
@ -17,9 +17,8 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityMergePullRequestBinding;
import org.mian.gitnex.fragments.PullRequestsFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.MergePullRequestSpinner;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.contexts.IssueContext;
import retrofit2.Call;
import retrofit2.Callback;
@ -29,11 +28,9 @@ import retrofit2.Callback;
*/
public class MergePullRequestActivity extends BaseActivity {
private View.OnClickListener onClickListener;
private IssueContext issue;
private ActivityMergePullRequestBinding viewBinding;
private String Do;
private final View.OnClickListener mergePullRequest = v -> processMergePullRequest();
@SuppressLint("SetTextI18n")
@Override
@ -46,26 +43,22 @@ public class MergePullRequestActivity extends BaseActivity {
issue = IssueContext.fromIntent(getIntent());
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
viewBinding.mergeTitle.requestFocus();
assert imm != null;
imm.showSoftInput(viewBinding.mergeTitle, InputMethodManager.SHOW_IMPLICIT);
setMergeAdapter();
if (!issue.getPullRequest().getTitle().isEmpty()) {
viewBinding.toolbarTitle.setText(issue.getPullRequest().getTitle());
viewBinding.topAppBar.setTitle(issue.getPullRequest().getTitle());
viewBinding.mergeTitle.setText(
issue.getPullRequest().getTitle() + " (#" + issue.getIssueIndex() + ")");
}
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
viewBinding.topAppBar.setNavigationOnClickListener(v -> finish());
MenuItem attachment = viewBinding.topAppBar.getMenu().getItem(0);
MenuItem markdown = viewBinding.topAppBar.getMenu().getItem(1);
MenuItem create = viewBinding.topAppBar.getMenu().getItem(2);
attachment.setVisible(false);
markdown.setVisible(false);
create.setTitle(getString(R.string.mergePullRequestButtonText));
// if gitea version is greater/equal(1.12.0) than user installed version
// (installed.higherOrEqual(compareVer))
@ -75,36 +68,37 @@ public class MergePullRequestActivity extends BaseActivity {
}
if (!issue.getPullRequest().isMergeable()) {
disableProcessButton();
viewBinding.mergeInfoDisabledMessage.setVisibility(View.VISIBLE);
create.setVisible(false);
} else {
viewBinding.mergeInfoDisabledMessage.setVisibility(View.GONE);
create.setVisible(true);
}
if (issue.prIsFork()) {
viewBinding.deleteBranchForkInfo.setVisibility(View.VISIBLE);
} else {
viewBinding.deleteBranchForkInfo.setVisibility(View.GONE);
}
if (!connToInternet) {
disableProcessButton();
} else {
viewBinding.mergeButton.setOnClickListener(mergePullRequest);
}
if (!(issue.getPullRequest().getHead().getRepo() != null
? issue.getPullRequest().getHead().getRepo().getPermissions().isPush()
: false)) {
viewBinding.deleteBranch.setVisibility(View.GONE);
viewBinding.deleteBranchForkInfo.setVisibility(View.GONE);
}
viewBinding.topAppBar.setOnMenuItemClickListener(
menuItem -> {
int id = menuItem.getItemId();
if (id == R.id.create) {
processMergePullRequest();
return true;
} else {
return super.onOptionsItemSelected(menuItem);
}
});
}
private void setMergeAdapter() {
@ -140,11 +134,6 @@ public class MergePullRequestActivity extends BaseActivity {
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
private void processMergePullRequest() {
String mergePRDesc =
@ -152,20 +141,14 @@ public class MergePullRequestActivity extends BaseActivity {
String mergePRTitle = Objects.requireNonNull(viewBinding.mergeTitle.getText()).toString();
boolean deleteBranch = viewBinding.deleteBranch.isChecked();
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
if (!connToInternet) {
Toasty.error(ctx, getResources().getString(R.string.checkNetConnection));
return;
}
if (Do == null) {
Toasty.error(ctx, getResources().getString(R.string.selectMergeStrategy));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.selectMergeStrategy));
} else {
disableProcessButton();
mergeFunction(Do, mergePRDesc, mergePRTitle, deleteBranch);
}
}
@ -237,49 +220,46 @@ public class MergePullRequestActivity extends BaseActivity {
}
}
Toasty.success(ctx, getString(R.string.mergePRSuccessMsg));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.mergePRSuccessMsg));
Intent result = new Intent();
PullRequestsFragment.resumePullRequests = true;
IssueDetailActivity.singleIssueUpdate = true;
RepoDetailActivity.updateRepo = true;
setResult(200, result);
finish();
new Handler().postDelayed(() -> finish(), 3000);
} else if (response.code() == 401) {
enableProcessButton();
AlertDialogs.authorizationTokenRevokedDialog(ctx);
} else if (response.code() == 404) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.mergePR404ErrorMsg));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.mergePR404ErrorMsg));
} else if (response.code() == 405) {
enableProcessButton();
Toasty.warning(ctx, getString(R.string.mergeNotAllowed));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.mergeNotAllowed));
} else {
enableProcessButton();
Toasty.error(ctx, getString(R.string.genericError));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
enableProcessButton();
}
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {}
});
}
private void disableProcessButton() {
viewBinding.mergeButton.setEnabled(false);
}
private void enableProcessButton() {
viewBinding.mergeButton.setEnabled(true);
}
@Override
public void onResume() {
super.onResume();

View File

@ -41,6 +41,7 @@ public class ProfileActivity extends BaseActivity implements BottomSheetListener
private String username;
private boolean following;
public ViewPager2 viewPager;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -64,7 +65,7 @@ public class ProfileActivity extends BaseActivity implements BottomSheetListener
Objects.requireNonNull(getSupportActionBar()).setTitle(username);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ViewPager2 viewPager = findViewById(R.id.profileContainer);
viewPager = findViewById(R.id.profileContainer);
viewPager.setOffscreenPageLimit(1);
TabLayout tabLayout = findViewById(R.id.tabs);

View File

@ -664,7 +664,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
mainIntent.removeExtra("goToSection");
mainIntent.removeExtra("goToSectionType");
switch (goToSectionType) {
switch (Objects.requireNonNull(goToSectionType)) {
case "branchesList":
viewPager.setCurrentItem(1);
chooseBranch();

View File

@ -1,14 +1,10 @@
package org.mian.gitnex.activities;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.TimePicker;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.timepicker.MaterialTimePicker;
import java.util.LinkedHashMap;
import java.util.Locale;
import org.mian.gitnex.R;
@ -16,8 +12,8 @@ import org.mian.gitnex.databinding.ActivitySettingsAppearanceBinding;
import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.FontsOverride;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
/**
* @author M M Arif
@ -28,7 +24,6 @@ public class SettingsAppearanceActivity extends BaseActivity {
private static int customFontSelectedChoice = 0;
private static String[] themeList;
private static int themeSelectedChoice = 0;
private View.OnClickListener onClickListener;
private static int langSelectedChoice = 0;
private static String[] fragmentTabsAnimationList;
private static int fragmentTabsAnimationSelectedChoice = 0;
@ -58,8 +53,7 @@ public class SettingsAppearanceActivity extends BaseActivity {
themeList = getResources().getStringArray(R.array.themes);
}
initCloseListener();
activitySettingsAppearanceBinding.close.setOnClickListener(onClickListener);
activitySettingsAppearanceBinding.topAppBar.setNavigationOnClickListener(v -> finish());
String lightMinute = String.valueOf(tinyDB.getInt("lightThemeTimeMinute"));
String lightHour = String.valueOf(tinyDB.getInt("lightThemeTimeHour"));
@ -112,7 +106,10 @@ public class SettingsAppearanceActivity extends BaseActivity {
activitySettingsAppearanceBinding.switchCounterBadge.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
tinyDB.putBoolean("enableCounterBadges", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
activitySettingsAppearanceBinding.counterBadgeFrame.setOnClickListener(
v ->
@ -126,7 +123,10 @@ public class SettingsAppearanceActivity extends BaseActivity {
activitySettingsAppearanceBinding.switchLabelsInListBadge.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
tinyDB.putBoolean("showLabelsInList", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
activitySettingsAppearanceBinding.labelsInListFrame.setOnClickListener(
v ->
@ -153,26 +153,20 @@ public class SettingsAppearanceActivity extends BaseActivity {
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceTheme.dismiss();
Toasty.success(
appCtx,
getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
});
activitySettingsAppearanceBinding.lightThemeTimeSelectionFrame.setOnClickListener(
view -> {
LightTimePicker timePicker = new LightTimePicker();
timePicker.show(getSupportFragmentManager(), "timePicker");
});
view -> lightTimePicker());
activitySettingsAppearanceBinding.darkThemeTimeSelectionFrame.setOnClickListener(
view -> {
DarkTimePicker timePicker = new DarkTimePicker();
timePicker.show(getSupportFragmentManager(), "timePicker");
});
view -> darkTimePicker());
// custom font dialog
activitySettingsAppearanceBinding.customFontFrame.setOnClickListener(
@ -196,10 +190,10 @@ public class SettingsAppearanceActivity extends BaseActivity {
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceCustomFont.dismiss();
Toasty.success(
appCtx,
appCtx.getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
@ -228,10 +222,10 @@ public class SettingsAppearanceActivity extends BaseActivity {
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceCustomFont.dismiss();
Toasty.success(
appCtx,
appCtx.getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
@ -239,9 +233,9 @@ public class SettingsAppearanceActivity extends BaseActivity {
// language selector dialog
activitySettingsAppearanceBinding.helpTranslate.setOnClickListener(
v12 -> {
AppUtil.openUrlInBrowser(this, getResources().getString(R.string.crowdInLink));
});
v12 ->
AppUtil.openUrlInBrowser(
this, getResources().getString(R.string.crowdInLink)));
langSelectedChoice = tinyDB.getInt("langId");
activitySettingsAppearanceBinding.tvLanguageSelected.setText(
@ -267,10 +261,10 @@ public class SettingsAppearanceActivity extends BaseActivity {
SettingsFragment.refreshParent = true;
this.overridePendingTransition(0, 0);
dialogInterface.dismiss();
Toasty.success(
appCtx,
getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
this.recreate();
});
@ -278,62 +272,56 @@ public class SettingsAppearanceActivity extends BaseActivity {
});
}
private void initCloseListener() {
onClickListener = view -> finish();
public void lightTimePicker() {
TinyDB db = TinyDB.getInstance(ctx);
int hour = db.getInt("lightThemeTimeHour");
int minute = db.getInt("lightThemeTimeMinute");
MaterialTimePicker materialTimePicker =
new MaterialTimePicker.Builder().setHour(hour).setMinute(minute).build();
materialTimePicker.addOnPositiveButtonClickListener(
selection -> {
db.putInt("lightThemeTimeHour", materialTimePicker.getHour());
db.putInt("lightThemeTimeMinute", materialTimePicker.getMinute());
SettingsFragment.refreshParent = true;
overridePendingTransition(0, 0);
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
recreate();
});
materialTimePicker.show(getSupportFragmentManager(), "fragmentManager");
}
public static class LightTimePicker extends DialogFragment
implements TimePickerDialog.OnTimeSetListener {
public void darkTimePicker() {
TinyDB db = TinyDB.getInstance(getContext());
TinyDB db = TinyDB.getInstance(ctx);
@NonNull @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int hour = db.getInt("lightThemeTimeHour");
int minute = db.getInt("lightThemeTimeMinute");
int hour = db.getInt("darkThemeTimeHour");
int minute = db.getInt("darkThemeTimeMinute");
return new TimePickerDialog(getActivity(), this, hour, minute, true);
}
MaterialTimePicker materialTimePicker =
new MaterialTimePicker.Builder().setHour(hour).setMinute(minute).build();
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
db.putInt("lightThemeTimeHour", hourOfDay);
db.putInt("lightThemeTimeMinute", minute);
SettingsFragment.refreshParent = true;
requireActivity().overridePendingTransition(0, 0);
this.dismiss();
Toasty.success(
requireActivity().getApplicationContext(),
requireContext().getResources().getString(R.string.settingsSave));
requireActivity().recreate();
}
}
materialTimePicker.addOnPositiveButtonClickListener(
selection -> {
db.putInt("darkThemeTimeHour", materialTimePicker.getHour());
db.putInt("darkThemeTimeMinute", materialTimePicker.getMinute());
SettingsFragment.refreshParent = true;
overridePendingTransition(0, 0);
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
recreate();
});
public static class DarkTimePicker extends DialogFragment
implements TimePickerDialog.OnTimeSetListener {
TinyDB db = TinyDB.getInstance(getContext());
@NonNull @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int hour = db.getInt("darkThemeTimeHour");
int minute = db.getInt("darkThemeTimeMinute");
return new TimePickerDialog(getActivity(), this, hour, minute, true);
}
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
db.putInt("darkThemeTimeHour", hourOfDay);
db.putInt("darkThemeTimeMinute", minute);
SettingsFragment.refreshParent = true;
requireActivity().overridePendingTransition(0, 0);
this.dismiss();
Toasty.success(
requireActivity().getApplicationContext(),
requireContext().getResources().getString(R.string.settingsSave));
requireActivity().recreate();
}
materialTimePicker.show(getSupportFragmentManager(), "fragmentManager");
}
private static String getLanguageDisplayName(String langCode) {

View File

@ -6,7 +6,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsCodeEditorBinding;
import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
/**
* @author M M Arif
@ -15,7 +15,6 @@ public class SettingsCodeEditorActivity extends BaseActivity {
private static String[] colorList;
private static int colorSelectedChoice = 0;
private View.OnClickListener onClickListener;
private static String[] indentationList;
private static int indentationSelectedChoice = 0;
private static String[] indentationTabsList;
@ -30,8 +29,7 @@ public class SettingsCodeEditorActivity extends BaseActivity {
ActivitySettingsCodeEditorBinding.inflate(getLayoutInflater());
setContentView(activitySettingsCodeEditorBinding.getRoot());
initCloseListener();
activitySettingsCodeEditorBinding.close.setOnClickListener(onClickListener);
activitySettingsCodeEditorBinding.topAppBar.setNavigationOnClickListener(v -> finish());
// color selector dialog
colorList = getResources().getStringArray(R.array.ceColors);
@ -56,10 +54,10 @@ public class SettingsCodeEditorActivity extends BaseActivity {
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceColor.dismiss();
Toasty.success(
appCtx,
getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
@ -90,10 +88,10 @@ public class SettingsCodeEditorActivity extends BaseActivity {
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceColor.dismiss();
Toasty.success(
appCtx,
getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
@ -132,17 +130,13 @@ public class SettingsCodeEditorActivity extends BaseActivity {
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceColor.dismiss();
Toasty.success(
appCtx,
getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -1,14 +1,13 @@
package org.mian.gitnex.activities;
import android.os.Bundle;
import android.view.View;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsGeneralBinding;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
/**
* @author M M Arif
@ -18,7 +17,6 @@ public class SettingsGeneralActivity extends BaseActivity {
private static int homeScreenSelectedChoice = 0;
private static int defaultLinkHandlerScreenSelectedChoice = 0;
private ActivitySettingsGeneralBinding viewBinding;
private View.OnClickListener onClickListener;
private List<String> homeScreenList;
private List<String> linkHandlerDefaultScreen;
@ -30,8 +28,7 @@ public class SettingsGeneralActivity extends BaseActivity {
viewBinding = ActivitySettingsGeneralBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
viewBinding.topAppBar.setNavigationOnClickListener(v -> finish());
// home screen
String[] appHomeDefaultScreen = getResources().getStringArray(R.array.appDefaultHomeScreen);
@ -118,10 +115,10 @@ public class SettingsGeneralActivity extends BaseActivity {
tinyDB.putInt("homeScreenId", i);
dialogInterfaceHomeScreen.dismiss();
Toasty.success(
appCtx,
getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
@ -156,10 +153,10 @@ public class SettingsGeneralActivity extends BaseActivity {
tinyDB.putInt("defaultScreenId", i);
dialogInterfaceHomeScreen.dismiss();
Toasty.success(
appCtx,
getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
@ -171,7 +168,10 @@ public class SettingsGeneralActivity extends BaseActivity {
viewBinding.switchTabs.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
tinyDB.putBoolean("useCustomTabs", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
viewBinding.customTabsFrame.setOnClickListener(
v -> viewBinding.switchTabs.setChecked(!viewBinding.switchTabs.isChecked()));
@ -185,7 +185,10 @@ public class SettingsGeneralActivity extends BaseActivity {
viewBinding.commentsDeletionSwitch.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
tinyDB.putBoolean("draftsCommentsDeletionEnabled", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
viewBinding.enableDraftsCommentsDeletion.setOnClickListener(
v ->
@ -197,7 +200,10 @@ public class SettingsGeneralActivity extends BaseActivity {
viewBinding.crashReportsSwitch.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
tinyDB.putBoolean("crashReportingEnabled", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
viewBinding.enableSendReports.setOnClickListener(
v ->
@ -205,8 +211,4 @@ public class SettingsGeneralActivity extends BaseActivity {
!viewBinding.crashReportsSwitch.isChecked()));
// crash reports switcher
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -1,16 +1,13 @@
package org.mian.gitnex.activities;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.NumberPicker;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsNotificationsBinding;
import org.mian.gitnex.fragments.SettingsFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.notifications.Notifications;
/**
@ -20,6 +17,8 @@ import org.mian.gitnex.notifications.Notifications;
public class SettingsNotificationsActivity extends BaseActivity {
private ActivitySettingsNotificationsBinding viewBinding;
private static String[] pollingDelayList;
private static int pollingDelayListSelectedChoice = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -29,35 +28,13 @@ public class SettingsNotificationsActivity extends BaseActivity {
viewBinding = ActivitySettingsNotificationsBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
View.OnClickListener onClickListener = viewClose -> finish();
viewBinding.close.setOnClickListener(onClickListener);
viewBinding.pollingDelaySelected.setText(
String.format(
getString(R.string.pollingDelaySelectedText),
tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay)));
viewBinding.chooseColorState.setCardBackgroundColor(
tinyDB.getInt("notificationsLightColor", Color.GREEN));
viewBinding.topAppBar.setNavigationOnClickListener(v -> finish());
viewBinding.enableNotificationsMode.setChecked(
tinyDB.getBoolean("notificationsEnabled", true));
viewBinding.enableLightsMode.setChecked(
tinyDB.getBoolean("notificationsEnableLights", true));
viewBinding.enableVibrationMode.setChecked(
tinyDB.getBoolean("notificationsEnableVibration", true));
if (!viewBinding.enableNotificationsMode.isChecked()) {
AppUtil.setMultiVisibility(
View.GONE,
viewBinding.chooseColorFrame,
viewBinding.enableLightsFrame,
viewBinding.enableVibrationFrame,
viewBinding.pollingDelayFrame);
}
if (!viewBinding.enableLightsMode.isChecked()) {
viewBinding.chooseColorFrame.setVisibility(View.GONE);
AppUtil.setMultiVisibility(View.GONE, viewBinding.pollingDelayFrame);
}
viewBinding.enableNotificationsMode.setOnCheckedChangeListener(
@ -66,23 +43,16 @@ public class SettingsNotificationsActivity extends BaseActivity {
if (isChecked) {
Notifications.startWorker(ctx);
AppUtil.setMultiVisibility(
View.VISIBLE,
viewBinding.chooseColorFrame,
viewBinding.enableLightsFrame,
viewBinding.enableVibrationFrame,
viewBinding.pollingDelayFrame);
AppUtil.setMultiVisibility(View.VISIBLE, viewBinding.pollingDelayFrame);
} else {
Notifications.stopWorker(ctx);
AppUtil.setMultiVisibility(
View.GONE,
viewBinding.chooseColorFrame,
viewBinding.enableLightsFrame,
viewBinding.enableVibrationFrame,
viewBinding.pollingDelayFrame);
AppUtil.setMultiVisibility(View.GONE, viewBinding.pollingDelayFrame);
}
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
viewBinding.enableNotificationsFrame.setOnClickListener(
v ->
@ -90,93 +60,39 @@ public class SettingsNotificationsActivity extends BaseActivity {
!viewBinding.enableNotificationsMode.isChecked()));
// polling delay
viewBinding.pollingDelayFrame.setOnClickListener(
v -> {
NumberPicker numberPicker = new NumberPicker(ctx);
numberPicker.setMinValue(Constants.minimumPollingDelay);
numberPicker.setMaxValue(Constants.maximumPollingDelay);
numberPicker.setValue(
tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay));
numberPicker.setWrapSelectorWheel(true);
pollingDelayList = getResources().getStringArray(R.array.notificationsPollingDelay);
pollingDelayListSelectedChoice = tinyDB.getInt("notificationsPollingDelayId");
viewBinding.pollingDelaySelected.setText(pollingDelayList[pollingDelayListSelectedChoice]);
viewBinding.pollingDelayFrame.setOnClickListener(
view -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
.setTitle(R.string.pollingDelayDialogHeaderText)
.setMessage(
getString(R.string.pollingDelayDialogDescriptionText))
.setCancelable(true)
.setNeutralButton(
R.string.cancelButton,
(dialog, which) -> dialog.dismiss())
.setPositiveButton(
getString(R.string.okButton),
(dialog, which) -> {
tinyDB.putInt(
"pollingDelayMinutes",
numberPicker.getValue());
.setSingleChoiceItems(
pollingDelayList,
pollingDelayListSelectedChoice,
(dialogInterfaceColor, i) -> {
pollingDelayListSelectedChoice = i;
viewBinding.pollingDelaySelected.setText(
pollingDelayList[
pollingDelayListSelectedChoice]);
tinyDB.putInt("notificationsPollingDelayId", i);
Notifications.stopWorker(ctx);
Notifications.startWorker(ctx);
viewBinding.pollingDelaySelected.setText(
String.format(
getString(
R.string
.pollingDelaySelectedText),
numberPicker.getValue()));
Toasty.success(
appCtx,
getResources()
.getString(R.string.settingsSave));
SettingsFragment.refreshParent = true;
this.recreate();
this.overridePendingTransition(0, 0);
dialogInterfaceColor.dismiss();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.setView(numberPicker);
materialAlertDialogBuilder.create().show();
});
// lights switcher
viewBinding.enableLightsMode.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
if (!isChecked) {
viewBinding.chooseColorFrame.setVisibility(View.GONE);
} else {
viewBinding.chooseColorFrame.setVisibility(View.VISIBLE);
}
tinyDB.putBoolean("notificationsEnableLights", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
viewBinding.enableLightsFrame.setOnClickListener(
v ->
viewBinding.enableLightsMode.setChecked(
!viewBinding.enableLightsMode.isChecked()));
// lights color chooser
viewBinding.chooseColorFrame.setOnClickListener(
v -> {
ColorPicker colorPicker = new ColorPicker(SettingsNotificationsActivity.this);
colorPicker.setColor(tinyDB.getInt("notificationsLightColor", Color.GREEN));
colorPicker.setCallback(
color -> {
tinyDB.putInt("notificationsLightColor", color);
viewBinding.chooseColorState.setCardBackgroundColor(color);
colorPicker.dismiss();
Toasty.success(
appCtx, getResources().getString(R.string.settingsSave));
});
colorPicker.show();
});
// vibration switcher
viewBinding.enableVibrationMode.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
tinyDB.putBoolean("notificationsEnableVibration", isChecked);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
viewBinding.enableVibrationFrame.setOnClickListener(
v ->
viewBinding.enableVibrationMode.setChecked(
!viewBinding.enableVibrationMode.isChecked()));
}
}

View File

@ -6,11 +6,6 @@ import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTI
import android.app.KeyguardManager;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.biometric.BiometricManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.io.File;
@ -19,7 +14,7 @@ import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsSecurityBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.ssl.MemorizingTrustManager;
/**
@ -31,7 +26,6 @@ public class SettingsSecurityActivity extends BaseActivity {
private static int cacheSizeDataSelectedChoice = 0;
private static String[] cacheSizeImagesList;
private static int cacheSizeImagesSelectedChoice = 0;
private View.OnClickListener onClickListener;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -42,33 +36,15 @@ public class SettingsSecurityActivity extends BaseActivity {
ActivitySettingsSecurityBinding.inflate(getLayoutInflater());
setContentView(activitySettingsSecurityBinding.getRoot());
ImageView closeActivity = activitySettingsSecurityBinding.close;
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
TextView cacheSizeDataSelected =
activitySettingsSecurityBinding.cacheSizeDataSelected; // setter for data cache size
TextView cacheSizeImagesSelected =
activitySettingsSecurityBinding
.cacheSizeImagesSelected; // setter for images cache size
TextView clearCacheSelected =
activitySettingsSecurityBinding.clearCacheSelected; // setter for clear cache
LinearLayout certsFrame = activitySettingsSecurityBinding.certsFrame;
LinearLayout cacheSizeDataFrame =
activitySettingsSecurityBinding.cacheSizeDataSelectionFrame;
LinearLayout cacheSizeImagesFrame =
activitySettingsSecurityBinding.cacheSizeImagesSelectionFrame;
LinearLayout clearCacheFrame = activitySettingsSecurityBinding.clearCacheSelectionFrame;
activitySettingsSecurityBinding.topAppBar.setNavigationOnClickListener(v -> finish());
cacheSizeDataList = getResources().getStringArray(R.array.cacheSizeList);
cacheSizeImagesList = getResources().getStringArray(R.array.cacheSizeList);
cacheSizeDataSelected.setText(
activitySettingsSecurityBinding.cacheSizeDataSelected.setText(
tinyDB.getString(
"cacheSizeStr", getString(R.string.cacheSizeDataSelectionSelectedText)));
cacheSizeImagesSelected.setText(
activitySettingsSecurityBinding.cacheSizeImagesSelected.setText(
tinyDB.getString(
"cacheSizeImagesStr",
getString(R.string.cacheSizeImagesSelectionSelectedText)));
@ -101,9 +77,10 @@ public class SettingsSecurityActivity extends BaseActivity {
BIOMETRIC_STRONG | DEVICE_CREDENTIAL)) {
case BiometricManager.BIOMETRIC_SUCCESS:
tinyDB.putBoolean("biometricStatus", true);
Toasty.success(
appCtx,
getResources().getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
break;
case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
case BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED:
@ -112,38 +89,45 @@ public class SettingsSecurityActivity extends BaseActivity {
tinyDB.putBoolean("biometricStatus", false);
activitySettingsSecurityBinding.switchBiometric.setChecked(
false);
Toasty.error(
appCtx,
getResources()
.getString(R.string.biometricNotSupported));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.biometricNotSupported));
break;
case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
tinyDB.putBoolean("biometricStatus", false);
activitySettingsSecurityBinding.switchBiometric.setChecked(
false);
Toasty.error(
appCtx,
getResources()
.getString(R.string.biometricNotAvailable));
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.biometricNotAvailable));
break;
case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
tinyDB.putBoolean("biometricStatus", false);
activitySettingsSecurityBinding.switchBiometric.setChecked(
false);
Toasty.info(
appCtx,
getResources().getString(R.string.enrollBiometric));
SnackBar.info(
ctx,
findViewById(android.R.id.content),
getString(R.string.enrollBiometric));
break;
}
} else {
tinyDB.putBoolean("biometricStatus", true);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
}
} else {
tinyDB.putBoolean("biometricStatus", false);
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
}
});
@ -154,11 +138,11 @@ public class SettingsSecurityActivity extends BaseActivity {
// clear cache setter
File cacheDir = appCtx.getCacheDir();
clearCacheSelected.setText(
activitySettingsSecurityBinding.clearCacheSelected.setText(
FileUtils.byteCountToDisplaySize((int) FileUtils.sizeOfDirectory(cacheDir)));
// clear cache
clearCacheFrame.setOnClickListener(
activitySettingsSecurityBinding.clearCacheSelectionFrame.setOnClickListener(
v1 -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
@ -180,7 +164,7 @@ public class SettingsSecurityActivity extends BaseActivity {
this.overridePendingTransition(0, 0);
} catch (IOException e) {
Log.e("SettingsSecurity", e.toString());
// Log.e("SettingsSecurity", e.toString());
}
});
@ -188,7 +172,7 @@ public class SettingsSecurityActivity extends BaseActivity {
});
// cache size images selection dialog
cacheSizeImagesFrame.setOnClickListener(
activitySettingsSecurityBinding.cacheSizeImagesSelectionFrame.setOnClickListener(
view -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
@ -199,7 +183,8 @@ public class SettingsSecurityActivity extends BaseActivity {
cacheSizeImagesSelectedChoice,
(dialogInterfaceTheme, i) -> {
cacheSizeImagesSelectedChoice = i;
cacheSizeImagesSelected.setText(
activitySettingsSecurityBinding
.cacheSizeImagesSelected.setText(
cacheSizeImagesList[i]);
tinyDB.putString(
"cacheSizeImagesStr",
@ -207,17 +192,17 @@ public class SettingsSecurityActivity extends BaseActivity {
tinyDB.putInt("cacheSizeImagesId", i);
dialogInterfaceTheme.dismiss();
Toasty.success(
appCtx,
getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
});
// cache size data selection dialog
cacheSizeDataFrame.setOnClickListener(
activitySettingsSecurityBinding.cacheSizeDataSelectionFrame.setOnClickListener(
view -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
@ -228,23 +213,25 @@ public class SettingsSecurityActivity extends BaseActivity {
cacheSizeDataSelectedChoice,
(dialogInterfaceTheme, i) -> {
cacheSizeDataSelectedChoice = i;
cacheSizeDataSelected.setText(cacheSizeDataList[i]);
activitySettingsSecurityBinding
.cacheSizeDataSelected.setText(
cacheSizeDataList[i]);
tinyDB.putString(
"cacheSizeStr", cacheSizeDataList[i]);
tinyDB.putInt("cacheSizeId", i);
dialogInterfaceTheme.dismiss();
Toasty.success(
appCtx,
getResources()
.getString(R.string.settingsSave));
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
});
// certs deletion
certsFrame.setOnClickListener(
activitySettingsSecurityBinding.certsFrame.setOnClickListener(
v1 -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
@ -271,9 +258,4 @@ public class SettingsSecurityActivity extends BaseActivity {
materialAlertDialogBuilder.create().show();
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -0,0 +1,125 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.card.MaterialCardView;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.io.FilenameUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.attachments.AttachmentsModel;
/**
* @author M M Arif
*/
public class AttachmentsAdapter extends RecyclerView.Adapter<AttachmentsAdapter.ViewHolder> {
private static AttachmentsReceiverListener AttachmentsReceiveListener;
private List<AttachmentsModel> attachmentsList;
private final Context ctx;
public AttachmentsAdapter(List<AttachmentsModel> attachmentsList, Context ctx) {
this.attachmentsList = attachmentsList;
this.ctx = ctx;
}
@Override
public int getItemCount() {
return attachmentsList == null ? 0 : attachmentsList.size();
}
@NonNull @Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view =
LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_attachments, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
AttachmentsModel currentItem = attachmentsList.get(position);
holder.attachmentsModel = currentItem;
holder.filename.setText(currentItem.getFileName());
if (Arrays.asList("bmp", "gif", "jpg", "jpeg", "png", "webp", "heic", "heif")
.contains(FilenameUtils.getExtension(currentItem.getFileName()).toLowerCase())) {
holder.attachmentViewFrame.setVisibility(View.VISIBLE);
PicassoService.getInstance(ctx)
.get()
.load(currentItem.getUri())
.placeholder(R.drawable.loader_animated)
.resize(120, 120)
.centerCrop()
.error(R.drawable.ic_close)
.into(holder.attachment);
} else {
holder.attachmentViewFrame.setVisibility(View.GONE);
}
}
class ViewHolder extends RecyclerView.ViewHolder {
public TextView filename;
public ImageView delete;
public MaterialCardView attachmentViewFrame;
public ImageView attachment;
private AttachmentsModel attachmentsModel;
public ViewHolder(View itemView) {
super(itemView);
filename = itemView.findViewById(R.id.filename);
delete = itemView.findViewById(R.id.delete_attachment);
attachmentViewFrame = itemView.findViewById(R.id.attachmentViewFrame);
attachment = itemView.findViewById(R.id.attachment);
delete.setOnClickListener(
itemDelete -> {
AttachmentsReceiveListener.setAttachmentsData(attachmentsModel.getUri());
deleteAttachment(getBindingAdapterPosition());
notifyDataChanged();
});
}
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
}
public void updateList(List<AttachmentsModel> list) {
attachmentsList = list;
notifyDataChanged();
}
private void deleteAttachment(int position) {
attachmentsList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, attachmentsList.size());
}
public interface AttachmentsReceiverListener {
void setAttachmentsData(Uri myData);
}
public static void setAttachmentsReceiveListener(
AttachmentsReceiverListener attachmentsListener) {
AttachmentsReceiveListener = attachmentsListener;
}
}

View File

@ -14,6 +14,7 @@ import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.text.HtmlCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.card.MaterialCardView;
import com.vdurmont.emoji.EmojiParser;
import java.util.List;
import java.util.Locale;
@ -72,7 +73,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
loadMoreListener.onLoadMore();
}
((DashboardAdapter.DashboardHolder) holder).bindData(activityList.get(position));
((DashboardAdapter.DashboardHolder) holder).bindData(activityList.get(position), position);
}
@Override
@ -123,6 +124,8 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
private final ImageView typeIcon;
private final TextView dashText;
private final LinearLayout dashTextFrame;
private LinearLayout dashboardLayoutCardsFrame;
private MaterialCardView cardLayout;
private Activity activityObject;
@ -135,6 +138,8 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
createdTime = itemView.findViewById(R.id.created_time);
dashText = itemView.findViewById(R.id.text);
dashTextFrame = itemView.findViewById(R.id.dash_text_frame);
dashboardLayoutCardsFrame = itemView.findViewById(R.id.dashboardLayoutCardsFrame);
cardLayout = itemView.findViewById(R.id.cardLayout);
new Handler()
.postDelayed(
@ -353,7 +358,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
200);
}
void bindData(Activity activity) {
void bindData(Activity activity, int position) {
this.activityObject = activity;
Locale locale = context.getResources().getConfiguration().locale;
@ -391,7 +396,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ "'>"
+ activity.getRepo().getFullName()
+ "</font>";
typeString = "created repository";
typeString = context.getString(R.string.createdRepository);
typeIcon.setImageResource(R.drawable.ic_repo);
} else if (activity.getOpType().equalsIgnoreCase("rename_repo")) {
@ -402,7 +407,10 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ "'>"
+ activity.getRepo().getFullName()
+ "</font>";
typeString = "renamed repository from " + activity.getContent() + " to";
typeString =
String.format(
context.getString(R.string.renamedRepository),
activity.getContent());
typeIcon.setImageResource(R.drawable.ic_repo);
} else if (activity.getOpType().equalsIgnoreCase("star_repo")) {
@ -413,7 +421,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ "'>"
+ activity.getRepo().getFullName()
+ "</font>";
typeString = "starred";
typeString = context.getString(R.string.starredRepository);
typeIcon.setImageResource(R.drawable.ic_star);
} else if (activity.getOpType().equalsIgnoreCase("transfer_repo")) {
@ -424,7 +432,10 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ "'>"
+ activity.getRepo().getFullName()
+ "</font>";
typeString = "transferred repository " + activity.getContent() + " to";
typeString =
String.format(
context.getString(R.string.transferredRepository),
activity.getContent());
typeIcon.setImageResource(R.drawable.ic_arrow_up);
} else if (activity.getOpType().equalsIgnoreCase("commit_repo")) {
@ -447,7 +458,8 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
activity.getRefName().lastIndexOf("/") + 1)
.trim()
+ "</font>";
typeString = "created branch " + branch + " in";
typeString =
String.format(context.getString(R.string.createdBranch), branch);
} else {
String branch =
"<font color='"
@ -459,7 +471,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
activity.getRefName().lastIndexOf("/") + 1)
.trim()
+ "</font>";
typeString = "pushed to " + branch + " at";
typeString = String.format(context.getString(R.string.pushedTo), branch);
JSONObject commitsObj = null;
try {
@ -567,7 +579,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "opened issue";
typeString = context.getString(R.string.openedIssue);
typeIcon.setImageResource(R.drawable.ic_issue);
} else if (activity.getOpType().equalsIgnoreCase("comment_issue")) {
@ -580,7 +592,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "commented on issue";
typeString = context.getString(R.string.commentedOnIssue);
typeIcon.setImageResource(R.drawable.ic_comment);
} else if (activity.getOpType().equalsIgnoreCase("close_issue")) {
@ -593,7 +605,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "closed issue";
typeString = context.getString(R.string.closedIssue);
typeIcon.setImageResource(R.drawable.ic_issue_closed);
} else if (activity.getOpType().equalsIgnoreCase("reopen_issue")) {
@ -606,7 +618,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "reopened issue";
typeString = context.getString(R.string.reopenedIssue);
typeIcon.setImageResource(R.drawable.ic_reopen);
}
} else if (activity.getOpType().contains("pull")) {
@ -634,7 +646,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "created pull request";
typeString = context.getString(R.string.createdPR);
typeIcon.setImageResource(R.drawable.ic_pull_request);
} else if (activity.getOpType().equalsIgnoreCase("close_pull_request")) {
@ -647,7 +659,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "closed pull request";
typeString = context.getString(R.string.closedPR);
typeIcon.setImageResource(R.drawable.ic_issue_closed);
} else if (activity.getOpType().equalsIgnoreCase("reopen_pull_request")) {
@ -660,7 +672,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "reopened pull request";
typeString = context.getString(R.string.reopenedPR);
typeIcon.setImageResource(R.drawable.ic_reopen);
} else if (activity.getOpType().equalsIgnoreCase("merge_pull_request")) {
@ -673,7 +685,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "merged pull request";
typeString = context.getString(R.string.mergedPR);
typeIcon.setImageResource(R.drawable.ic_pull_request);
} else if (activity.getOpType().equalsIgnoreCase("approve_pull_request")) {
@ -686,7 +698,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "approved";
typeString = context.getString(R.string.approved);
typeIcon.setImageResource(R.drawable.ic_done);
} else if (activity.getOpType().equalsIgnoreCase("reject_pull_request")) {
@ -699,7 +711,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "suggested changes for";
typeString = context.getString(R.string.suggestedChanges);
typeIcon.setImageResource(R.drawable.ic_diff);
} else if (activity.getOpType().equalsIgnoreCase("comment_pull")) {
@ -712,7 +724,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "commented on pull request";
typeString = context.getString(R.string.commentedOnPR);
typeIcon.setImageResource(R.drawable.ic_comment);
} else if (activity.getOpType().equalsIgnoreCase("auto_merge_pull_request")) {
@ -725,7 +737,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ context.getResources().getString(R.string.hash)
+ id
+ "</font>";
typeString = "automatically merged pull request";
typeString = context.getString(R.string.autoMergePR);
typeIcon.setImageResource(R.drawable.ic_issue_closed);
}
} else if (activity.getOpType().contains("branch")) {
@ -758,7 +770,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
.trim()
+ "</font>";
typeString = "deleted branch " + branch + " at";
typeString = String.format(context.getString(R.string.deletedBranch), branch);
typeIcon.setImageResource(R.drawable.ic_commit);
}
} else if (activity.getOpType().contains("tag")) {
@ -783,7 +795,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
.trim()
+ "</font>";
typeString = "pushed tag " + branch + " to";
typeString = String.format(context.getString(R.string.pushedTag), branch);
typeIcon.setImageResource(R.drawable.ic_commit);
} else if (activity.getOpType().equalsIgnoreCase("delete_tag")) {
@ -805,7 +817,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
.trim()
+ "</font>";
typeString = "deleted tag " + branch + " from";
typeString = String.format(context.getString(R.string.deletedTag), branch);
typeIcon.setImageResource(R.drawable.ic_commit);
}
} else if (activity.getOpType().contains("release")) {
@ -830,7 +842,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
.trim()
+ "</font>";
typeString = "released " + branch + " at";
typeString = String.format(context.getString(R.string.releasedBranch), branch);
typeIcon.setImageResource(R.drawable.ic_tag);
}
} else if (activity.getOpType().contains("mirror")) {
@ -845,7 +857,8 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ activity.getRepo().getFullName()
+ "</font>";
typeString = "synced commits to " + headerString + " at";
typeString =
String.format(context.getString(R.string.syncedCommits), headerString);
typeIcon.setImageResource(R.drawable.ic_tag);
} else if (activity.getOpType().equalsIgnoreCase("mirror_sync_create")) {
@ -857,7 +870,8 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ activity.getRepo().getFullName()
+ "</font>";
typeString = "synced new reference " + headerString + " to";
typeString =
String.format(context.getString(R.string.syncedRefs), headerString);
typeIcon.setImageResource(R.drawable.ic_tag);
} else if (activity.getOpType().equalsIgnoreCase("mirror_sync_delete")) {
@ -869,7 +883,9 @@ public class DashboardAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
+ activity.getRepo().getFullName()
+ "</font>";
typeString = "synced and deleted reference " + headerString + " at";
typeString =
String.format(
context.getString(R.string.syncedDeletedRefs), headerString);
typeIcon.setImageResource(R.drawable.ic_tag);
}
} else {

View File

@ -32,11 +32,15 @@ import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.card.MaterialCardView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.vdurmont.emoji.EmojiParser;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.gitnex.tea4j.v2.models.Attachment;
import org.gitnex.tea4j.v2.models.TimelineComment;
import org.json.JSONArray;
import org.json.JSONException;
@ -48,6 +52,7 @@ import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.CustomImageViewDialogBinding;
import org.mian.gitnex.fragments.BottomSheetReplyFragment;
import org.mian.gitnex.fragments.IssuesFragment;
import org.mian.gitnex.helpers.AlertDialogs;
@ -257,6 +262,15 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<RecyclerView.View
timelineDividerView = view.findViewById(R.id.timeline_divider_view);
timelineLine2 = view.findViewById(R.id.timeline_line_2);
String token = ((BaseActivity) context).getAccount().getAccount().getToken();
new Handler()
.postDelayed(
() -> {
getAttachments(issueComment.getId(), view, token);
},
250);
menu.setOnClickListener(
v -> {
final String loginUid =
@ -888,20 +902,42 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<RecyclerView.View
}
if (issueComment.getType().equalsIgnoreCase("review")) {
timelineView.setVisibility(View.GONE);
timelineDividerView.setVisibility(View.GONE);
if (!issueComment.getBody().equalsIgnoreCase("")) {
start.setText(
context.getString(
R.string.timelineReviewLeftComment,
issueComment.getUser().getLogin(),
issueComment.getBody(),
info));
timelineIcon.setImageDrawable(
ContextCompat.getDrawable(context, R.drawable.ic_comment));
} else {
timelineView.setVisibility(View.GONE);
timelineDividerView.setVisibility(View.GONE);
}
} else if (issueComment.getType().equalsIgnoreCase("dismiss_review")) {
timelineView.setVisibility(View.GONE);
timelineDividerView.setVisibility(View.GONE);
} else if (issueComment.getType().equalsIgnoreCase("review_request")) {
String reviewer;
if (issueComment.getAssignee() != null) {
reviewer = issueComment.getAssignee().getLogin();
} else {
if (issueComment.getAssigneeTeam() != null) {
reviewer = issueComment.getAssigneeTeam().getName();
} else {
reviewer = "";
}
}
start.setText(
context.getString(
R.string.timelineReviewRequest,
issueComment.getUser().getLogin(),
issueComment.getAssignee().getLogin(),
reviewer,
info));
timelineIcon.setImageDrawable(
ContextCompat.getDrawable(context, R.drawable.ic_unwatch));
ContextCompat.getDrawable(context, R.drawable.ic_watchers));
}
start.setTextSize(fontSize);
@ -1286,4 +1322,133 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<RecyclerView.View
}
}
}
private void getAttachments(Long issueIndex, View view, String token) {
LinearLayout attachmentFrame = view.findViewById(R.id.attachmentFrame);
LinearLayout attachmentsView = view.findViewById(R.id.attachmentsView);
Call<List<Attachment>> call =
RetrofitClient.getApiInterface(context)
.issueListIssueCommentAttachments(
issue.getRepository().getOwner(),
issue.getRepository().getName(),
issueIndex);
call.enqueue(
new Callback<>() {
@Override
public void onResponse(
@NonNull Call<List<Attachment>> call,
@NonNull retrofit2.Response<List<Attachment>> response) {
List<Attachment> attachment = response.body();
if (response.code() == 200) {
assert attachment != null;
if (attachment.size() > 0) {
attachmentFrame.setVisibility(View.VISIBLE);
LinearLayout.LayoutParams paramsAttachment =
new LinearLayout.LayoutParams(96, 96);
paramsAttachment.setMargins(0, 0, 48, 0);
for (int i = 0; i < attachment.size(); i++) {
ImageView attachmentView = new ImageView(context);
MaterialCardView materialCardView =
new MaterialCardView(context);
materialCardView.setLayoutParams(paramsAttachment);
materialCardView.setStrokeWidth(0);
materialCardView.setCardBackgroundColor(Color.TRANSPARENT);
if (Arrays.asList(
"bmp", "gif", "jpg", "jpeg", "png", "webp",
"heic", "heif")
.contains(
FilenameUtils.getExtension(
attachment.get(i).getName())
.toLowerCase())) {
PicassoService.getInstance(context)
.get()
.load(
attachment.get(i).getBrowserDownloadUrl()
+ "?token="
+ token)
.placeholder(R.drawable.loader_animated)
.resize(120, 120)
.centerCrop()
.error(R.drawable.ic_close)
.into(attachmentView);
attachmentsView.addView(materialCardView);
attachmentView.setLayoutParams(paramsAttachment);
materialCardView.addView(attachmentView);
int finalI1 = i;
materialCardView.setOnClickListener(
v1 ->
imageViewDialog(
attachment
.get(finalI1)
.getBrowserDownloadUrl(),
token));
} else {
attachmentView.setImageResource(
R.drawable.ic_file_download);
attachmentView.setPadding(4, 4, 4, 4);
attachmentsView.addView(materialCardView);
attachmentView.setLayoutParams(paramsAttachment);
materialCardView.addView(attachmentView);
int finalI = i;
materialCardView.setOnClickListener(
v1 -> {
// filesize = attachment.get(finalI).getSize();
// filename = attachment.get(finalI).getName();
// filehash = attachment.get(finalI).getUuid();
// requestFileDownload();
});
}
}
} else {
attachmentFrame.setVisibility(View.GONE);
}
}
}
@Override
public void onFailure(
@NonNull Call<List<Attachment>> call, @NonNull Throwable t) {}
});
}
private void imageViewDialog(String url, String token) {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(
context, R.style.ThemeOverlay_Material3_Dialog_Alert);
CustomImageViewDialogBinding imageViewDialogBinding =
CustomImageViewDialogBinding.inflate(LayoutInflater.from(context));
View view = imageViewDialogBinding.getRoot();
materialAlertDialogBuilder.setView(view);
materialAlertDialogBuilder.setNeutralButton(context.getString(R.string.close), null);
PicassoService.getInstance(context)
.get()
.load(url + "?token=" + token)
.placeholder(R.drawable.loader_animated)
.resize(0, 1600)
.onlyScaleDown()
.centerCrop()
.error(R.drawable.ic_close)
.into(imageViewDialogBinding.imageView);
materialAlertDialogBuilder.create().show();
}
}

View File

@ -8,6 +8,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
@ -41,7 +42,6 @@ public class MostVisitedReposAdapter
private final TextView repoName;
private final TextView orgName;
private final TextView mostVisited;
private final ImageView resetCounter;
private MostVisitedViewHolder(View itemView) {
@ -51,7 +51,7 @@ public class MostVisitedReposAdapter
repoName = itemView.findViewById(R.id.repo_name);
orgName = itemView.findViewById(R.id.org_name);
mostVisited = itemView.findViewById(R.id.most_visited);
resetCounter = itemView.findViewById(R.id.reset_counter);
LinearLayout repoInfoEndFrame = itemView.findViewById(R.id.repo_info_end_frame);
itemView.setOnClickListener(
v -> {
@ -66,7 +66,7 @@ public class MostVisitedReposAdapter
context.startActivity(intent);
});
resetCounter.setOnClickListener(
repoInfoEndFrame.setOnClickListener(
itemDelete -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(

View File

@ -161,6 +161,15 @@ public class RetrofitClient {
((BaseActivity) context).getAccount().getCacheDir(context));
}
public static WebApi getWebInterface(Context context, String url) {
return getWebInterface(
context,
url,
((BaseActivity) context).getAccount().getAuthorization(),
((BaseActivity) context).getAccount().getCacheDir(context));
}
public static ApiInterface getApiInterface(
Context context, String url, String token, File cacheFile) {

View File

@ -30,7 +30,7 @@ import org.mian.gitnex.databinding.FragmentNotificationsBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.SimpleCallback;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.contexts.IssueContext;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
@ -53,6 +53,7 @@ public class NotificationsFragment extends Fragment
private int pageCurrentIndex = 1;
private int pageResultLimit;
private String currentFilterMode = "unread";
public static String emptyErrorResponse;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@ -119,21 +120,51 @@ public class NotificationsFragment extends Fragment
(call, voidResponse) -> {
if (voidResponse.isPresent()
&& voidResponse.get().isSuccessful()) {
Toasty.success(
SnackBar.success(
context,
requireActivity()
.findViewById(
android.R.id
.content),
getString(
R.string
.markedNotificationsAsRead));
pageCurrentIndex = 1;
loadNotifications(false);
} else {
activity.runOnUiThread(
() ->
Toasty.error(
context,
getString(
R.string
.genericError)));
if (!emptyErrorResponse.isEmpty()) {
if (emptyErrorResponse.contains(
"205")) {
SnackBar.success(
context,
requireActivity()
.findViewById(
android.R.id
.content),
getString(
R.string
.markedNotificationsAsRead));
pageCurrentIndex = 1;
loadNotifications(false);
}
} else {
activity.runOnUiThread(
() ->
SnackBar.error(
context,
requireActivity()
.findViewById(
android
.R
.id
.content),
getString(
R.string
.genericError)));
}
}
}));

View File

@ -101,18 +101,18 @@ public class RepoInfoFragment extends Fragment {
binding.fileContentsFrameHeader.setOnClickListener(v1 -> toggleExpandView());
binding.repoMetaFrameHeader.setOnClickListener(v12 -> toggleExpandViewMeta());
binding.repoMetaStarsFrame.setOnClickListener(
binding.repoMetaStars.setOnClickListener(
metaStars ->
ctx.startActivity(repository.getIntent(ctx, RepoStargazersActivity.class)));
binding.repoMetaWatchersFrame.setOnClickListener(
binding.repoMetaWatchers.setOnClickListener(
metaWatchers ->
ctx.startActivity(repository.getIntent(ctx, RepoWatchersActivity.class)));
binding.repoMetaForksFrame.setOnClickListener(
binding.repoMetaForks.setOnClickListener(
metaForks -> ctx.startActivity(repository.getIntent(ctx, RepoForksActivity.class)));
binding.repoMetaPullRequestsFrame.setOnClickListener(
binding.repoMetaPullRequests.setOnClickListener(
metaPR -> ((RepoDetailActivity) requireActivity()).viewPager.setCurrentItem(3));
setLanguageStatistics();
@ -405,7 +405,7 @@ public class RepoInfoFragment extends Fragment {
if (repoInfo.getOpenPrCounter() != null) {
binding.repoMetaPullRequests.setText(String.valueOf(repoInfo.getOpenPrCounter()));
} else {
binding.repoMetaPullRequestsFrame.setVisibility(View.GONE);
binding.repoMetaPullRequests.setVisibility(View.GONE);
}
binding.repoMetaForks.setText(String.valueOf(repoInfo.getForksCount()));

View File

@ -13,6 +13,7 @@ import okhttp3.ResponseBody;
import org.gitnex.tea4j.v2.models.Repository;
import org.gitnex.tea4j.v2.models.User;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentProfileDetailBinding;
@ -69,6 +70,16 @@ public class DetailFragment extends Fragment {
getProfileDetail(username);
getProfileRepository(username);
binding.userFollowersCount.setOnClickListener(
metaFollowersFrame ->
((ProfileActivity) requireActivity()).viewPager.setCurrentItem(4));
binding.userFollowingCount.setOnClickListener(
metaFollowingFrame ->
((ProfileActivity) requireActivity()).viewPager.setCurrentItem(5));
binding.userStarredReposCount.setOnClickListener(
metaStarredReposFrame ->
((ProfileActivity) requireActivity()).viewPager.setCurrentItem(2));
return binding.getRoot();
}
@ -106,11 +117,22 @@ public class DetailFragment extends Fragment {
binding.userEmail.setText(email);
binding.userFollowersCount.setText(
String.valueOf(response.body().getFollowersCount()));
String.valueOf(
response.body().getFollowersCount()
+ " "
+ getString(
R.string.profileTabFollowers)));
binding.userFollowingCount.setText(
String.valueOf(response.body().getFollowingCount()));
String.valueOf(
response.body().getFollowingCount()
+ " "
+ getString(
R.string.profileTabFollowing)));
binding.userStarredReposCount.setText(
String.valueOf(response.body().getStarredReposCount()));
String.valueOf(
response.body().getStarredReposCount()
+ " "
+ getString(R.string.starredRepos)));
String[] userLanguageCodes =
response.body().getLanguage().split("-");

View File

@ -297,6 +297,10 @@ public class AppUtil {
return str.matches("^[\\w .-]+$");
}
public static Boolean checkLabel(String str) { // [a-zA-Z0-9-_. /:]
return str.matches("^[\\w .-/:]+$");
}
public static Boolean checkStringsWithAlphaNumericDashDotUnderscore(
String str) { // [a-zA-Z0-9-_]
return str.matches("^[\\w.-]+$");

View File

@ -6,6 +6,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
@ -216,6 +217,9 @@ public class Markdown {
}
}
textView.setTypeface(tf);
textView.setTextIsSelectable(true);
textView.setMovementMethod(
LinkMovementMethod.getInstance());
super.beforeSetText(textView, markdown);
}
@ -382,6 +386,9 @@ public class Markdown {
}
}
textView.setTypeface(tf);
textView.setTextIsSelectable(true);
textView.setMovementMethod(
LinkMovementMethod.getInstance());
super.beforeSetText(textView, markdown);
}

View File

@ -1,10 +1,8 @@
package org.mian.gitnex.helpers;
import android.util.Log;
import androidx.annotation.NonNull;
import java.io.File;
import java.util.Optional;
import java.util.stream.Collectors;
import org.mian.gitnex.fragments.NotificationsFragment;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@ -22,10 +20,6 @@ public interface SimpleCallback<T> extends Callback<T> {
default void onFailure(@NonNull Call<T> call, @NonNull Throwable throwable) {
onFinished(call, Optional.empty());
Log.e(
call.request().url().pathSegments().stream()
.collect(Collectors.joining(File.pathSeparator)),
throwable.toString());
NotificationsFragment.emptyErrorResponse = throwable.getMessage();
}
}

View File

@ -15,6 +15,7 @@ public class SnackBar {
Snackbar snackBar = Snackbar.make(view, message, Snackbar.LENGTH_LONG);
View sbView = snackBar.getView();
TextView textView = sbView.findViewById(R.id.snackbar_text);
snackBar.setBackgroundTint(context.getColor(R.color.material_dynamic_neutral10));
textView.setTextColor(context.getColor(R.color.colorWhite));
snackBar.show();
}
@ -23,7 +24,8 @@ public class SnackBar {
Snackbar snackBar = Snackbar.make(view, message, Snackbar.LENGTH_LONG);
View sbView = snackBar.getView();
TextView textView = sbView.findViewById(R.id.snackbar_text);
textView.setTextColor(context.getColor(R.color.colorLightGreen));
snackBar.setBackgroundTint(context.getColor(R.color.material_dynamic_neutral10));
textView.setTextColor(context.getColor(R.color.colorWhite));
snackBar.show();
}
@ -31,7 +33,8 @@ public class SnackBar {
Snackbar snackBar = Snackbar.make(view, message, Snackbar.LENGTH_LONG);
View sbView = snackBar.getView();
TextView textView = sbView.findViewById(R.id.snackbar_text);
textView.setTextColor(context.getColor(R.color.lightYellow));
snackBar.setBackgroundTint(context.getColor(R.color.material_dynamic_neutral10));
textView.setTextColor(context.getColor(R.color.warningColor));
snackBar.show();
}
@ -39,6 +42,7 @@ public class SnackBar {
Snackbar snackBar = Snackbar.make(view, message, Snackbar.LENGTH_LONG);
View sbView = snackBar.getView();
TextView textView = sbView.findViewById(R.id.snackbar_text);
snackBar.setBackgroundTint(context.getColor(R.color.material_dynamic_neutral10));
textView.setTextColor(context.getColor(R.color.darkRed));
snackBar.show();
}

View File

@ -0,0 +1,60 @@
package org.mian.gitnex.helpers.attachments;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
/**
* @author M M Arif
*/
public class AttachmentUtils {
public static File getFile(Context ctx, Uri uri) {
File destinationFilename;
try {
destinationFilename =
new File(
ctx.getFilesDir().getPath() + File.separatorChar + queryName(ctx, uri));
} catch (AssertionError e) {
destinationFilename = new File(uri.getPath());
}
try (InputStream ins = ctx.getContentResolver().openInputStream(uri)) {
createFileFromStream(ins, destinationFilename);
} catch (Exception ex) {
ex.printStackTrace();
}
return destinationFilename;
}
public static String queryName(Context ctx, Uri uri) {
Cursor returnCursor = ctx.getContentResolver().query(uri, null, null, null, null);
assert returnCursor != null;
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
String name = returnCursor.getString(nameIndex);
returnCursor.close();
return name;
}
public static void createFileFromStream(InputStream ins, File destination) {
try (OutputStream os = new FileOutputStream(destination)) {
byte[] buffer = new byte[4096];
int length;
while ((length = ins.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
os.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

View File

@ -0,0 +1,42 @@
package org.mian.gitnex.helpers.attachments;
import android.net.Uri;
/**
* @author M M Arif
*/
public class AttachmentsModel {
private Uri uri;
private String fileName;
private long fileSize;
public AttachmentsModel(String fileName, Uri uri) {
this.fileName = fileName;
this.uri = uri;
}
public Uri getUri() {
return uri;
}
public void setUri(Uri uri) {
this.uri = uri;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
}

View File

@ -3,13 +3,17 @@ package org.mian.gitnex.notifications;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Color;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import androidx.core.app.NotificationManagerCompat;
import androidx.work.Constraints;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.concurrent.TimeUnit;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.Constants;
@ -34,16 +38,11 @@ public class Notifications {
public static void createChannels(Context context) {
TinyDB tinyDB = TinyDB.getInstance(context);
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Delete old notification channels
notificationManager.deleteNotificationChannel(
context.getPackageName()); // TODO Can be removed in future versions
// Create new notification channels
NotificationChannel mainChannel =
new NotificationChannel(
@ -53,20 +52,6 @@ public class Notifications {
mainChannel.setDescription(
context.getString(R.string.mainNotificationChannelDescription));
if (tinyDB.getBoolean("notificationsEnableVibration", true)) {
mainChannel.setVibrationPattern(Constants.defaultVibrationPattern);
mainChannel.enableVibration(true);
} else {
mainChannel.enableVibration(false);
}
if (tinyDB.getBoolean("notificationsEnableLights", true)) {
mainChannel.setLightColor(tinyDB.getInt("notificationsLightColor", Color.GREEN));
mainChannel.enableLights(true);
} else {
mainChannel.enableLights(false);
}
NotificationChannel downloadChannel =
new NotificationChannel(
Constants.downloadNotificationChannelId,
@ -89,8 +74,48 @@ public class Notifications {
TinyDB tinyDB = TinyDB.getInstance(context);
int delay;
if (tinyDB.getInt("notificationsPollingDelayId") == 0) {
delay = 15;
} else if (tinyDB.getInt("notificationsPollingDelayId") == 1) {
delay = 30;
} else if (tinyDB.getInt("notificationsPollingDelayId") == 2) {
delay = 45;
} else if (tinyDB.getInt("notificationsPollingDelayId") == 3) {
delay = 60;
} else {
delay = Constants.defaultPollingDelay;
}
if (tinyDB.getBoolean("notificationsEnabled", true)) {
if (!NotificationManagerCompat.from(context).areNotificationsEnabled()) {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(context)
.setTitle(R.string.pageTitleNotifications)
.setMessage(context.getString(R.string.openAppSettings))
.setNeutralButton(
R.string.cancelButton, (dialog, which) -> dialog.dismiss())
.setPositiveButton(
R.string.isOpen,
(dialog, which) -> {
Intent intent =
new Intent(
Settings
.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri =
Uri.fromParts(
"package",
context.getPackageName(),
null);
intent.setData(uri);
context.startActivity(intent);
});
materialAlertDialogBuilder.create().show();
return;
}
Constraints.Builder constraints =
new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
@ -98,20 +123,11 @@ public class Notifications {
.setRequiresStorageNotLow(false)
.setRequiresCharging(false);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
constraints.setRequiresDeviceIdle(false);
}
int pollingDelayMinutes =
Math.max(
tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay),
15);
constraints.setRequiresDeviceIdle(false);
PeriodicWorkRequest periodicWorkRequest =
new PeriodicWorkRequest.Builder(
NotificationsWorker.class,
pollingDelayMinutes,
TimeUnit.MINUTES)
NotificationsWorker.class, delay, TimeUnit.MINUTES)
.setConstraints(constraints.build())
.addTag(Constants.notificationsWorkerId)
.build();
@ -119,7 +135,7 @@ public class Notifications {
WorkManager.getInstance(context)
.enqueueUniquePeriodicWork(
Constants.notificationsWorkerId,
ExistingPeriodicWorkPolicy.KEEP,
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
periodicWorkRequest);
}
}

View File

@ -1,17 +1,23 @@
package org.mian.gitnex.notifications;
import android.Manifest;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.content.pm.PackageManager;
import android.media.RingtoneManager;
import android.net.Uri;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.app.TaskStackBuilder;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import java.util.Date;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.time.ZonedDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -22,7 +28,6 @@ import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Version;
@ -35,7 +40,6 @@ import retrofit2.Response;
public class NotificationsWorker extends Worker {
private final Context context;
private final TinyDB tinyDB;
private final Map<UserAccount, Map<String, String>> userAccounts;
public NotificationsWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
@ -45,9 +49,27 @@ public class NotificationsWorker extends Worker {
UserAccountsApi userAccountsApi = BaseApi.getInstance(context, UserAccountsApi.class);
this.context = context;
this.tinyDB = TinyDB.getInstance(context);
TinyDB tinyDB = TinyDB.getInstance(context);
assert userAccountsApi != null;
this.userAccounts = new HashMap<>(userAccountsApi.getCount());
int delay;
if (tinyDB.getInt("notificationsPollingDelayId") == 0) {
delay = 15;
} else if (tinyDB.getInt("notificationsPollingDelayId") == 1) {
delay = 30;
} else if (tinyDB.getInt("notificationsPollingDelayId") == 2) {
delay = 45;
} else if (tinyDB.getInt("notificationsPollingDelayId") == 3) {
delay = 60;
} else {
delay = Constants.defaultPollingDelay;
}
ZonedDateTime zdt = ZonedDateTime.now();
zdt = zdt.minusMinutes(delay);
String previousTimestamp = String.valueOf(zdt.toOffsetDateTime());
for (UserAccount userAccount : userAccountsApi.loggedInUserAccounts()) {
// We do also accept empty values, since the server version was not saved properly in
@ -57,8 +79,7 @@ public class NotificationsWorker extends Worker {
|| new Version(userAccount.getServerVersion()).higherOrEqual("1.12.3")) {
Map<String, String> userAccountParameters = new HashMap<>();
userAccountParameters.put(
"previousTimestamp", AppUtil.getTimestampFromDate(context, new Date()));
userAccountParameters.put("previousTimestamp", previousTimestamp);
userAccounts.put(userAccount, userAccountParameters);
}
@ -67,56 +88,31 @@ public class NotificationsWorker extends Worker {
@NonNull @Override
public Result doWork() {
pollingLoops();
startPolling();
return Result.success();
}
/** Used to bypass the 15-minute limit of {@code WorkManager}. */
private void pollingLoops() {
int notificationLoops =
tinyDB.getInt("pollingDelayMinutes", Constants.defaultPollingDelay) < 15
? Math.min(
15
- tinyDB.getInt(
"pollingDelayMinutes",
Constants.defaultPollingDelay),
10)
: 1;
for (int i = 0; i < notificationLoops; i++) {
long startPollingTime = System.currentTimeMillis();
startPolling();
try {
if (notificationLoops > 1 && i < (notificationLoops - 1)) {
Thread.sleep(60000 - (System.currentTimeMillis() - startPollingTime));
}
} catch (InterruptedException ignored) {
}
}
}
private void startPolling() {
for (UserAccount userAccount : userAccounts.keySet()) {
Map<String, String> userAccountParameters = userAccounts.get(userAccount);
assert userAccountParameters != null;
try {
assert userAccountParameters != null;
Call<List<NotificationThread>> call =
RetrofitClient.getApiInterface(
context,
userAccount.getInstanceUrl(),
userAccount.getToken(),
"token " + userAccount.getToken(),
null)
.notifyGetList(
.notifyGetList2(
false,
List.of("unread"),
null,
new Date(userAccountParameters.get("previousTimestamp")),
userAccountParameters.get("previousTimestamp"),
null,
null,
1);
1,
25);
Response<List<NotificationThread>> response = call.execute();
@ -125,8 +121,6 @@ public class NotificationsWorker extends Worker {
if (!notificationThreads.isEmpty()) {
sendNotifications(userAccount, notificationThreads);
}
userAccountParameters.put(
"previousTimestamp", AppUtil.getTimestampFromDate(context, new Date()));
}
} catch (Exception ignored) {
}
@ -153,10 +147,37 @@ public class NotificationsWorker extends Worker {
.setSmallIcon(R.drawable.gitnex_transparent)
.setGroup(userAccount.getUserName())
.setGroupSummary(true)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
if (ActivityCompat.checkSelfPermission(
getApplicationContext(), Manifest.permission.POST_NOTIFICATIONS)
!= PackageManager.PERMISSION_GRANTED) {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(context)
.setTitle(R.string.pageTitleNotifications)
.setMessage(context.getString(R.string.openAppSettings))
.setNeutralButton(
R.string.cancelButton, (dialog, which) -> dialog.dismiss())
.setPositiveButton(
R.string.isOpen,
(dialog, which) -> {
Intent intent =
new Intent(
Settings
.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri =
Uri.fromParts(
"package", context.getPackageName(), null);
intent.setData(uri);
context.startActivity(intent);
});
materialAlertDialogBuilder.create().show();
return;
}
notificationManagerCompat.notify(userAccount.getAccountId(), summaryNotification);
for (NotificationThread notificationThread : notificationThreads) {
@ -189,25 +210,12 @@ public class NotificationsWorker extends Worker {
private NotificationCompat.Builder getBaseNotificationBuilder() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context, Constants.mainNotificationChannelId)
.setSmallIcon(R.drawable.gitnex_transparent)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true);
if (tinyDB.getBoolean("notificationsEnableLights", true)) {
builder.setLights(tinyDB.getInt("notificationsLightColor", Color.GREEN), 1500, 1500);
}
if (tinyDB.getBoolean("notificationsEnableVibration", true)) {
builder.setVibrate(Constants.defaultVibrationPattern);
} else {
builder.setVibrate(null);
}
return builder;
return new NotificationCompat.Builder(context, Constants.mainNotificationChannelId)
.setSmallIcon(R.drawable.gitnex_transparent)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true);
}
private PendingIntent getPendingIntent(@NonNull UserAccount userAccount) {
@ -218,7 +226,10 @@ public class NotificationsWorker extends Worker {
intent.putExtra("switchAccountId", userAccount.getAccountId());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return PendingIntent.getActivity(
context, userAccount.getAccountId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntentWithParentStack(intent);
return stackBuilder.getPendingIntent(
1, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
}

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="m21.44,11.05 l-9.19,9.19a6,6 0,0 1,-8.49 -8.49l8.57,-8.57A4,4 0,1 1,18 8.84l-8.59,8.57a2,2 0,0 1,-2.83 -2.83l8.49,-8.48"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M14.5,2H6a2,2 0,0 0,-2 2v16a2,2 0,0 0,2 2h12a2,2 0,0 0,2 -2V7.5L14.5,2z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M14,2l0,6l6,0"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M12,18v-6"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="m9,15 l3,3 3,-3"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -3,25 +3,25 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#00000000"
android:pathData="M3,12L21,12"
android:strokeWidth="2"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"
android:strokeLineJoin="round"/>
<path
android:fillColor="#00000000"
android:pathData="M3,6L21,6"
android:strokeWidth="2"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"
android:strokeLineJoin="round"/>
<path
android:fillColor="#00000000"
android:pathData="M3,18L21,18"
android:strokeWidth="2"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"
android:strokeLineJoin="round"/>
<path
android:pathData="M5,3L19,3A2,2 0,0 1,21 5L21,19A2,2 0,0 1,19 21L5,21A2,2 0,0 1,3 19L3,5A2,2 0,0 1,5 3z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M9,3v18"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="m14,9 l3,3 -3,3"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

View File

@ -3,10 +3,10 @@
android:shape="rectangle">
<corners
android:topLeftRadius="@dimen/dimen32dp"
android:topRightRadius="@dimen/dimen32dp"/>
android:topLeftRadius="@dimen/dimen28dp"
android:topRightRadius="@dimen/dimen28dp"/>
<padding android:top="@dimen/dimen24dp"/>
<padding android:top="@dimen/dimen28dp"/>
<solid android:color="?attr/primaryBackgroundColor"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?attr/primaryBackgroundColor"/>
<solid android:color="?attr/materialCardBackgroundColor"/>
<corners android:radius="18dp"/>
</shape>

View File

@ -1,72 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
tools:ignore="UnusedAttribute">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/pageTitleAddEmail"
app:layout_collapseMode="pin"
app:menu="@menu/save"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/pageTitleAddEmail"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/userEmailLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/accountEmailTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/userEmailLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/accountEmailTitle"
android:textColorHint="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/userEmail"
@ -79,15 +69,8 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/addEmailButton"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/saveButton"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -67,7 +67,6 @@
android:id="@+id/addCollaboratorSearchLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:boxBackgroundColor="?attr/inputBackgroundColor"
android:textColorHint="?attr/hintColor"
app:hintTextColor="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"

View File

@ -1,155 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/layoutNewAccount"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp"
app:layout_constraintTop_toTopOf="parent">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:contentDescription="@string/close"
android:gravity="center_vertical"
android:src="@drawable/ic_arrow_back"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/addNewAccount"
app:layout_collapseMode="pin"
app:menu="@menu/add_new_account_menu"
app:navigationIcon="@drawable/ic_arrow_back" />
<TextView
android:id="@+id/toolbarTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="@dimen/dimen20dp"
android:ellipsize="none"
android:scrollbars="horizontal"
android:singleLine="true"
android:text="@string/addNewAccount"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp"
app:layout_constraintTop_toTopOf="parent">
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/protocolSpinnerLayout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/protocol"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
android:orientation="vertical"
android:padding="@dimen/dimen16dp"
app:layout_constraintTop_toTopOf="parent">
<AutoCompleteTextView
android:id="@+id/protocolSpinner"
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/protocolSpinnerLayout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:inputType="none"
android:labelFor="@+id/protocolSpinner"
android:textColor="?attr/inputTextColor"
android:textSize="@dimen/dimen16sp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/instanceUrlLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/instanceUrl"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_link"
app:startIconTint="?attr/iconsColor"
app:helperText="@string/instanceHelperText">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/instanceUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/protocol"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
</com.google.android.material.textfield.TextInputLayout>
<AutoCompleteTextView
android:id="@+id/protocolSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:inputType="none"
android:labelFor="@+id/protocolSpinner"
android:textColor="?attr/inputTextColor"
android:textSize="@dimen/dimen16sp" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/loginTokenLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/copyToken"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_lock"
app:startIconTint="?attr/iconsColor">
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/loginToken"
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/instanceUrlLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/instanceUrl"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_link"
app:startIconTint="?attr/iconsColor"
app:helperText="@string/instanceHelperText">
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/instanceUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/addNewAccount"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/addNewAccountText"
android:textColor="?attr/materialCardBackgroundColor"
android:textSize="@dimen/dimen16sp"
android:textStyle="bold"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/loginTokenLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/copyToken"
android:textColorHint="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_lock"
app:startIconTint="?attr/iconsColor">
</LinearLayout>
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/loginToken"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,55 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/pageTitleNewFile"
app:layout_collapseMode="pin"
app:menu="@menu/file_create_edit_menu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbarTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/pageTitleNewFile"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
@ -65,7 +54,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newFileNameTintCopy"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -95,7 +83,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newFileContentTintCopy"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -135,7 +122,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newFileBranches"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:helperText="@string/newFileEmptyBranchMessage"
app:helperTextEnabled="true"
@ -164,7 +150,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newFileMessageTintCopy"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:counterEnabled="true"
app:counterMaxLength="255"
@ -186,17 +171,8 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/newFileCreate"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/newFileButtonCopy"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,48 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close" />
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/pageTitleCreateNewIssue"
app:layout_collapseMode="pin"
app:menu="@menu/create_issue_menu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/pageTitleCreateNewIssue"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp" />
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
@ -53,18 +42,18 @@
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone"
app:indicatorColor="?attr/progressIndicatorColor"/>
app:indicatorColor="?attr/progressIndicatorColor" />
<ScrollView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueTitleLayout"
@ -74,7 +63,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:counterEnabled="true"
app:counterMaxLength="255"
@ -97,7 +85,7 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueDescriptionLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -105,7 +93,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueDescriptionTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -123,9 +110,9 @@
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/markdown_preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -137,7 +124,7 @@
android:textSize="@dimen/dimen14sp"
android:visibility="gone" />
<com.google.android.material.textfield.TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueAssigneesListLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -145,7 +132,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueAssigneesListTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:hintTextColor="?attr/hintColor">
<com.google.android.material.textfield.TextInputEditText
@ -158,9 +144,9 @@
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueMilestoneSpinnerLayout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
@ -169,7 +155,7 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueMilestoneTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxBackgroundColor="?attr/primaryBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
@ -182,9 +168,9 @@
android:textColor="?attr/inputTextColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueLabelsLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -192,7 +178,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueLabelsTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:hintTextColor="?attr/hintColor">
<com.google.android.material.textfield.TextInputEditText
@ -205,9 +190,9 @@
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueDueDateLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -215,7 +200,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueDueDateTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -226,13 +210,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:maxLines="1"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/createNewIssueButton"
@ -241,10 +224,11 @@
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/newCreateButtonCopy"
android:textColor="?attr/materialCardBackgroundColor"
android:visibility="gone"
android:textStyle="bold" />
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,125 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/pageTitleCreateLabel"
app:layout_collapseMode="pin"
app:menu="@menu/create_label_menu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/pageTitleCreateLabel"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/labelNameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/labelName"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/labelName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
</com.google.android.material.textfield.TextInputLayout>
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dimen32dp"
android:layout_marginTop="@dimen/dimen10dp"
android:orientation="horizontal">
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/labelText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight=".95"
android:gravity="center_vertical"
android:text="@string/labelColor"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/labelNameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/labelName"
android:textColorHint="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewElevatedStyle"
android:layout_width="@dimen/dimen28dp"
android:layout_height="@dimen/dimen28dp"
app:cardCornerRadius="@dimen/dimen16dp"
app:cardElevation="@dimen/dimen0dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/labelName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dimen32dp"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="horizontal">
<TextView
android:id="@+id/colorPicker"
android:layout_width="match_parent"
android:id="@+id/labelText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@color/releasePre"/>
android:layout_gravity="center_vertical"
android:layout_weight=".95"
android:gravity="center_vertical"
android:text="@string/labelColor"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp"/>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewElevatedStyle"
android:layout_width="@dimen/dimen48dp"
android:layout_height="@dimen/dimen28dp"
app:cardCornerRadius="@dimen/dimen16dp"
app:cardElevation="@dimen/dimen0dp">
<TextView
android:id="@+id/colorPicker"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/releasePre" />
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/createLabelButton"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/newCreateButtonCopy"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,55 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/pageTitleCreateMilestone"
app:layout_collapseMode="pin"
app:menu="@menu/create_issue_menu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/pageTitleCreateMilestone"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
@ -65,7 +54,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newMilestoneTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -93,7 +81,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newMilestoneDescription"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:counterEnabled="true"
app:counterMaxLength="255"
@ -136,7 +123,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newMilestoneDueDate"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -155,18 +141,9 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/createNewMilestoneButton"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/newCreateButtonCopy"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,61 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/adminCreateNewUser"
app:layout_collapseMode="pin"
app:menu="@menu/create_issue_menu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/adminCreateNewUser"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/fullNameLayout"
@ -65,7 +54,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/userFullNameText"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -93,7 +81,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/userUserName"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -120,7 +107,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/userEmail"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -147,7 +133,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/userPassword"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -165,17 +150,8 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/createUserButton"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/newCreateButtonCopy"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,61 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/pageTitleCreateOrganization"
app:layout_collapseMode="pin"
app:menu="@menu/create_issue_menu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/pageTitleCreateOrganization"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newOrganizationNameLayout"
@ -65,7 +54,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newOrgTintCopy"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -93,7 +81,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newOrgDescTintCopy"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:counterEnabled="true"
app:counterMaxLength="255"
@ -116,18 +103,8 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/createNewOrganizationButton"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/newCreateButtonCopy"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,48 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/pageTitleNewPullRequest"
app:layout_collapseMode="pin"
app:menu="@menu/create_issue_menu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbarTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/pageTitleNewPullRequest"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
@ -53,12 +42,12 @@
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone"
app:indicatorColor="?attr/progressIndicatorColor"/>
app:indicatorColor="?attr/progressIndicatorColor" />
<ScrollView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
@ -74,7 +63,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:counterEnabled="true"
app:counterMaxLength="255"
@ -105,7 +93,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueDescriptionTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -146,7 +133,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/mergeIntoBranch"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
@ -170,7 +156,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/pullFromBranch"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
@ -194,7 +179,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueMilestoneTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
@ -217,7 +201,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueLabelsTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:hintTextColor="?attr/hintColor">
<com.google.android.material.textfield.TextInputEditText
@ -240,7 +223,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueDueDateTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -259,17 +241,8 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/createPr"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/newCreateButtonCopy"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,61 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/createRelease"
app:layout_collapseMode="pin"
app:menu="@menu/create_release_tag_menu"
app:popupTheme="@style/Widget.Material3.PopupMenu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/createRelease"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/releaseTitleLayout"
@ -65,7 +55,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/releaseTitleText"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -93,7 +82,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/releaseTagNameText"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -121,7 +109,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/releaseContentText"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -162,7 +149,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/releaseBranchText"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
@ -197,26 +183,8 @@
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/createNewRelease"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/newCreateButtonCopy"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/createNewTag"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/create_tag"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,55 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/pageTitleNewRepo"
app:layout_collapseMode="pin"
app:menu="@menu/create_issue_menu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/pageTitleNewRepo"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
@ -66,7 +55,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newRepoOwner"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
@ -77,7 +65,7 @@
android:inputType="none"
android:labelFor="@+id/ownerSpinner"
android:textColor="?attr/inputTextColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
@ -89,7 +77,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newRepoTintCopy"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -103,7 +90,56 @@
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/defaultBranchFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/infoTabRepoDefaultBranch"
android:textColorHint="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/defaultBranch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapSentences"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:text="@string/main"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/issueLabelsFrame"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newRepoIssueLabels"
android:textColorHint="?attr/hintColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
<AutoCompleteTextView
android:id="@+id/issueLabels"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:labelFor="@+id/issueLabels"
android:textColor="?attr/inputTextColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
@ -115,7 +151,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newRepoDescTintCopy"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:counterEnabled="true"
app:counterMaxLength="255"
@ -133,7 +168,30 @@
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/licenseFrame"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/license"
android:textColorHint="?attr/hintColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
<AutoCompleteTextView
android:id="@+id/licenses"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:labelFor="@+id/licenses"
android:textColor="?attr/inputTextColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
@ -145,21 +203,20 @@
android:checked="true"
android:text="@string/newRepoPrivateCopy"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/createNewRepoButton"
<CheckBox
android:id="@+id/setAsTemplate"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/newCreateButtonCopy"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen10dp"
android:checked="false"
android:text="@string/setAsTemplate"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
</ScrollView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,61 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/pageTitleCreateTeam"
app:layout_collapseMode="pin"
app:menu="@menu/create_issue_menu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/pageTitleCreateTeam"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/teamNameLayout"
@ -65,7 +54,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newTeamTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -81,7 +69,7 @@
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
@ -93,7 +81,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newTeamDesc"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:counterEnabled="true"
app:counterMaxLength="255"
@ -111,7 +98,7 @@
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
@ -123,7 +110,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newTeamPermission"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:hintTextColor="?attr/hintColor">
@ -136,7 +122,7 @@
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
@ -147,7 +133,7 @@
android:gravity="start"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen12sp"
android:visibility="gone"/>
android:visibility="gone" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/teamAccessControlsLayout"
@ -157,7 +143,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newTeamAccessControls"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:hintTextColor="?attr/hintColor">
@ -170,7 +155,7 @@
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
@ -178,19 +163,10 @@
android:id="@+id/teamAccessControlsArray"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/createTeamButton"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/newCreateButtonCopy"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
android:visibility="gone" />
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,61 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/editIssueNavHeader"
app:layout_collapseMode="pin"
app:menu="@menu/create_issue_menu"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/editIssueNavHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/editIssueTitleLayout"
@ -65,7 +54,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -93,7 +81,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueDescriptionTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -134,7 +121,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueMilestoneTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
@ -157,7 +143,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueDueDateTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -176,17 +161,8 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/editIssueButton"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/saveButton"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -132,197 +132,231 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/materialCardBackgroundColor"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="@dimen/dimen12dp">
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewElevatedStyle"
android:layout_width="@dimen/dimen24dp"
android:layout_height="@dimen/dimen24dp"
app:cardCornerRadius="@dimen/dimen12dp"
app:cardElevation="@dimen/dimen0dp">
<ImageView
android:id="@+id/assigneeAvatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0"
android:contentDescription="@string/generalImgContentText"
tools:srcCompat="@tools:sample/avatars"
tools:ignore="TooDeepLayout" />
</com.google.android.material.card.MaterialCardView>
android:layout_height="wrap_content"
android:background="?attr/materialCardBackgroundColor"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="@dimen/dimen12dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dimen16dp"
android:layout_marginRight="@dimen/dimen16dp"
android:layout_weight="1"
android:orientation="vertical">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="middle"
android:singleLine="true"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp"
android:textStyle="bold" />
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewElevatedStyle"
android:layout_width="@dimen/dimen24dp"
android:layout_height="@dimen/dimen24dp"
app:cardCornerRadius="@dimen/dimen12dp"
app:cardElevation="@dimen/dimen0dp">
<ImageView
android:id="@+id/assigneeAvatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0"
android:contentDescription="@string/generalImgContentText"
tools:srcCompat="@tools:sample/avatars"
tools:ignore="TooDeepLayout" />
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:layout_marginLeft="@dimen/dimen16dp"
android:layout_marginRight="@dimen/dimen16dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/issueCreatedTime"
android:id="@+id/author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:textColor="?attr/hintColor"
android:textSize="12sp"
android:visibility="gone" />
android:ellipsize="middle"
android:singleLine="true"
android:textIsSelectable="true"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/issueModified"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:text="@string/modifiedText"
android:textColor="?attr/hintColor"
android:textSize="12sp"
android:visibility="gone" />
android:orientation="horizontal">
<TextView
android:id="@+id/issueCreatedTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:textColor="?attr/hintColor"
android:textSize="12sp"
android:visibility="gone" />
<TextView
android:id="@+id/issueModified"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:text="@string/modifiedText"
android:textColor="?attr/hintColor"
android:textSize="12sp"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/dueDateFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end|center_vertical"
android:orientation="horizontal"
android:visibility="gone"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="@dimen/dimen20dp"
<LinearLayout
android:id="@+id/dueDateFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_calendar" />
android:gravity="end|center_vertical"
android:orientation="horizontal"
android:visibility="gone"
tools:ignore="UseCompoundDrawables">
<TextView
android:id="@+id/issueDueDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen8dp"
android:singleLine="true"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
<ImageView
android:layout_width="@dimen/dimen20dp"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_calendar" />
</LinearLayout>
<TextView
android:id="@+id/issueDueDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen8dp"
android:singleLine="true"
android:textIsSelectable="true"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
<LinearLayout
android:id="@+id/milestoneFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end|center_vertical"
android:orientation="horizontal"
android:visibility="gone"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="@dimen/dimen20dp"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_milestone" />
<TextView
android:id="@+id/issueMilestone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen8dp"
android:singleLine="true"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
<HorizontalScrollView
android:id="@+id/assigneesScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:foregroundGravity="right"
android:visibility="gone"
android:scrollbarThumbHorizontal="@android:color/transparent">
</LinearLayout>
<LinearLayout
android:id="@+id/frameAssignees"
android:layout_width="wrap_content"
android:id="@+id/milestoneFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end|center_vertical"
android:orientation="horizontal"
android:visibility="gone"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="@dimen/dimen20dp"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_milestone" />
<TextView
android:id="@+id/issueMilestone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen8dp"
android:singleLine="true"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
<HorizontalScrollView
android:id="@+id/assigneesScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:foregroundGravity="right"
android:visibility="gone"
android:scrollbarThumbHorizontal="@android:color/transparent">
<LinearLayout
android:id="@+id/frameAssignees"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="@dimen/dimen10dp"
android:gravity="end"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/issueDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/dimen8dp"
android:autoLink="web"
android:gravity="start"
android:visibility="gone"
android:textColor="?attr/primaryTextColor"
android:textColorLink="@color/lightBlue"
android:textIsSelectable="true"
android:textSize="@dimen/dimen14sp" />
<HorizontalScrollView
android:id="@+id/labelsScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:foregroundGravity="right"
android:visibility="gone"
android:scrollbarThumbHorizontal="@android:color/transparent">
<LinearLayout
android:id="@+id/frameLabels"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen10dp"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
<LinearLayout
android:id="@+id/commentReactionBadges"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="@dimen/dimen10dp"
android:gravity="end"
android:orientation="horizontal"
android:visibility="gone" />
</LinearLayout>
<LinearLayout
android:id="@+id/attachmentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/materialCardBackgroundColor"
android:foreground="?android:attr/selectableItemBackground"
android:visibility="gone"
android:orientation="vertical">
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen4dp" />
<LinearLayout
android:id="@+id/attachmentsView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/dimen12dp"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/issueDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/dimen8dp"
android:autoLink="web"
android:gravity="start"
android:visibility="gone"
android:textColor="?attr/primaryTextColor"
android:textColorLink="@color/lightBlue"
android:textIsSelectable="true"
android:textSize="@dimen/dimen14sp" />
<HorizontalScrollView
android:id="@+id/labelsScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:foregroundGravity="right"
android:visibility="gone"
android:scrollbarThumbHorizontal="@android:color/transparent">
<LinearLayout
android:id="@+id/frameLabels"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen10dp"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
<LinearLayout
android:id="@+id/commentReactionBadges"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen10dp"
android:orientation="horizontal"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>

View File

@ -1,268 +1,269 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/loginForm"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:gravity="center"
android:orientation="vertical">
android:background="@drawable/login_bg">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:alpha="0.6" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
android:gravity="center"
android:layout_above="@id/card_view">
<ImageView
android:layout_width="@dimen/dimen100dp"
android:layout_height="@dimen/dimen100dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/dimen20dp"
android:layout_marginBottom="@dimen/dimen20dp"
android:layout_width="@dimen/dimen80dp"
android:layout_height="@dimen/dimen80dp"
android:baselineAligned="false"
android:contentDescription="@string/appName"
android:src="@mipmap/app_logo"/>
android:src="@mipmap/app_logo" />
<TextView
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen10dp"
android:gravity="start"
android:text="@string/loginMethodText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen12sp"/>
<RadioGroup
android:id="@+id/loginMethod"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:orientation="vertical">
<RadioButton
android:id="@+id/loginToken"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen36dp"
android:checked="true"
android:text="@string/copyToken"
android:textColor="?attr/primaryTextColor"/>
<RadioButton
android:id="@+id/loginUsernamePassword"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen36dp"
android:text="@string/loginViaPassword"
android:textColor="?attr/primaryTextColor"/>
</RadioGroup>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/httpsSpinnerLayout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/protocol"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
<AutoCompleteTextView
android:id="@+id/httpsSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:labelFor="@+id/httpsSpinner"
android:textColor="?attr/inputTextColor"
android:textSize="@dimen/dimen16sp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/instance_urlLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/instanceUrl"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_link"
app:startIconTint="?attr/iconsColor"
app:helperText="@string/instanceHelperText">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/instance_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textUri"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/login_uidLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/userName"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_person"
app:startIconTint="?attr/iconsColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/login_uid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/login_passwdLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/passWord"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="password_toggle"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_lock"
app:startIconTint="?attr/iconsColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/login_passwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/otpCodeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/loginOTP"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:helperText="@string/otpMessage"
app:helperTextEnabled="true"
app:helperTextTextColor="?attr/inputTextColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_otp"
app:startIconTint="?attr/iconsColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/otpCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/loginTokenCodeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/copyToken"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_lock"
app:startIconTint="?attr/iconsColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/loginTokenCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/login_button"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/btnLogin"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen10dp"
android:layout_marginTop="@dimen/dimen20dp"
android:layout_marginEnd="@dimen/dimen10dp"
android:autoLink="web"
android:gravity="center"
android:text="@string/appRepoLink"
android:textColor="?attr/primaryTextColor"
android:textColorLink="@color/lightBlue"
android:textSize="@dimen/dimen14sp"/>
android:text="@string/appName"
android:textStyle="bold"
android:textSize="@dimen/dimen24sp"
android:textColor="@color/colorWhite"
android:layout_marginTop="@dimen/dimen8dp" />
<TextView
android:id="@+id/appVersion"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen6dp"
android:layout_weight="1"
android:maxLines="1"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp"/>
android:textColor="@color/colorWhite"
android:textSize="@dimen/dimen12sp" />
</LinearLayout>
</ScrollView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="-28dp"
android:alpha="0.9"
app:cardCornerRadius="@dimen/dimen32dp"
app:strokeWidth="@dimen/dimen0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen28dp">
<RadioGroup
android:id="@+id/loginMethod"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/loginToken"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen36dp"
android:checked="true"
android:text="@string/copyToken"
android:layout_marginEnd="@dimen/dimen8dp"
android:textColor="?attr/inputTextColor" />
<RadioButton
android:id="@+id/loginUsernamePassword"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen36dp"
android:text="@string/loginViaPassword"
android:textColor="?attr/inputTextColor" />
</RadioGroup>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/httpsSpinnerLayout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/protocol"
android:textColorHint="?attr/hintColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
<AutoCompleteTextView
android:id="@+id/httpsSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:labelFor="@+id/httpsSpinner"
android:textColor="?attr/inputTextColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/instance_urlLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/instanceUrl"
android:textColorHint="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_link"
app:startIconTint="?attr/iconsColor"
app:helperText="@string/instanceHelperText">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/instance_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textUri"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/login_uidLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/userName"
android:textColorHint="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_person"
app:startIconTint="?attr/iconsColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/login_uid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/login_passwdLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/passWord"
android:textColorHint="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="password_toggle"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_lock"
app:startIconTint="?attr/iconsColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/login_passwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/otpCodeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/loginOTP"
android:textColorHint="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:helperText="@string/otpMessage"
app:helperTextEnabled="true"
app:helperTextTextColor="?attr/inputTextColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_otp"
app:startIconTint="?attr/iconsColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/otpCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/loginTokenCodeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/copyToken"
android:textColorHint="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor"
app:startIconDrawable="@drawable/ic_lock"
app:startIconTint="?attr/iconsColor">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/loginTokenCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/login_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen16dp"
android:text="@string/btnLogin"
android:textColor="?attr/materialCardBackgroundColor"
android:letterSpacing="0.1"
android:textStyle="bold" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</RelativeLayout>

View File

@ -1,72 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/mergePullRequestButtonText"
app:layout_collapseMode="pin"
app:menu="@menu/create_issue_menu"
app:navigationIcon="@drawable/ic_close" />
<HorizontalScrollView
android:id="@+id/replyToPRNavHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen0dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:fillViewport="true"
android:foregroundGravity="right"
android:scrollbarThumbHorizontal="@android:color/transparent">
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</HorizontalScrollView>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/mergeTitleLayout"
@ -76,7 +54,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/mergePullRequestButtonText"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:counterEnabled="true"
app:counterMaxLength="255"
@ -95,7 +72,7 @@
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
@ -107,7 +84,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/mergeCommentText"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -122,7 +98,7 @@
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
@ -135,7 +111,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/mergeStrategy"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:endIconTint="?attr/iconsColor"
app:hintTextColor="?attr/hintColor">
@ -146,7 +121,7 @@
android:inputType="none"
android:labelFor="@+id/mergeSpinner"
android:textColor="?attr/inputTextColor"
android:textSize="@dimen/dimen16sp"/>
android:textSize="@dimen/dimen16sp" />
</com.google.android.material.textfield.TextInputLayout>
@ -159,17 +134,17 @@
android:text="@string/deleteBranchAfterMerge"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp"
android:visibility="gone"/>
android:visibility="gone" />
<TextView
android:id="@+id/deleteBranchForkInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen0dp"
android:layout_marginTop="@dimen/dimen10dp"
android:gravity="start"
android:text="@string/deleteBranchForkInfo"
android:textColor="?attr/hintColor"
android:textSize="@dimen/dimen12sp"/>
android:textSize="@dimen/dimen12sp" />
<TextView
android:id="@+id/mergeInfo"
@ -179,16 +154,7 @@
android:gravity="start"
android:text="@string/mergeNoteText"
android:textColor="?attr/hintColor"
android:textSize="@dimen/dimen12sp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/mergeButton"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_marginTop="@dimen/dimen8dp"
android:text="@string/mergePullRequestButtonText"
android:textColor="?attr/materialCardBackgroundColor"
android:textStyle="bold"/>
android:textSize="@dimen/dimen12sp" />
<TextView
android:id="@+id/mergeInfoDisabledMessage"
@ -199,11 +165,11 @@
android:text="@string/mergeInfoDisabledMessage"
android:textColor="?attr/hintColor"
android:textSize="@dimen/dimen12sp"
android:visibility="gone"/>
android:visibility="visible" />
</LinearLayout>
</ScrollView>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,351 +1,299 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen10dp"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
android:theme="@style/AppTheme.AppBarOverlay">
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/settingsAppearanceHeader"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/settingsAppearanceHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:id="@+id/themeSelectionFrame"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/themeHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/themeSelectionHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<TextView
android:id="@+id/themeSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/themeSelectionSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/lightThemeTimeSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/lightThemeTimeHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsLightThemeTimeSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<TextView
android:id="@+id/lightThemeSelectedTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsThemeTimeSelectedHint"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/darkThemeTimeSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/darkThemeTimeHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsDarkThemeTimeSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<TextView
android:id="@+id/darkThemeSelectedTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsThemeTimeSelectedHint"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/customFontFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/customFontHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsCustomFontHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<TextView
android:id="@+id/customFontSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsCustomFontDefault"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/fragmentTabsAnimationFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/fragmentTabsAnimationFrameHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/fragmentTabsAnimationHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<TextView
android:id="@+id/fragmentTabsAnimationFrameSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/fadeOut"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
</LinearLayout>
<RelativeLayout
android:id="@+id/counterBadgeFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/tvCounterBadgeHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen48dp"
android:text="@string/settingsCounterBadges"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switchCounterBadge"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen24dp"
android:layout_alignParentEnd="true"
android:layout_gravity="end"
android:layout_toEndOf="@+id/tvCounterBadgeHeader"
android:gravity="end"
android:paddingStart="@dimen/dimen0dp"
android:paddingEnd="@dimen/dimen24dp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/labelsInListFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:padding="@dimen/dimen16dp">
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/label_title_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="100"
android:orientation="horizontal">
<TextView
android:id="@+id/tvLabelsInListHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="90"
android:layout_marginStart="@dimen/dimen24dp"
android:text="@string/settingsLabelsInListHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<LinearLayout
android:layout_width="wrap_content"
android:id="@+id/themeSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="10"
android:gravity="center_vertical|end"
android:orientation="horizontal">
android:clickable="true"
android:focusable="true"
android:layout_marginTop="@dimen/dimen8dp"
android:orientation="vertical">
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switchLabelsInListBadge"
<TextView
android:id="@+id/themeHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen32dp"
android:paddingStart="@dimen/dimen24dp"
android:paddingEnd="@dimen/dimen24dp" />
android:layout_height="wrap_content"
android:text="@string/themeSelectionHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/themeSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/themeSelectionSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/lightThemeTimeSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
<TextView
android:id="@+id/lightThemeTimeHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsLightThemeTimeSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/lightThemeSelectedTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsThemeTimeSelectedHint"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/darkThemeTimeSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
<TextView
android:id="@+id/darkThemeTimeHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsDarkThemeTimeSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/darkThemeSelectedTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsThemeTimeSelectedHint"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/customFontFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
<TextView
android:id="@+id/customFontHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsCustomFontHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/customFontSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsCustomFontDefault"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/fragmentTabsAnimationFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
<TextView
android:id="@+id/fragmentTabsAnimationFrameHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/fragmentTabsAnimationHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/fragmentTabsAnimationFrameSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/fadeOut"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/counterBadgeFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tvCounterBadgeHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".90"
android:text="@string/settingsCounterBadges"
android:layout_marginTop="@dimen/dimen4dp"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switchCounterBadge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/settingsCounterBadges"
android:layout_weight=".10" />
</LinearLayout>
<LinearLayout
android:id="@+id/labelsInListFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tvLabelsInListHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".90"
android:text="@string/settingsLabelsInListHeader"
android:layout_marginTop="@dimen/dimen4dp"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switchLabelsInListBadge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/settingsLabelsInListHeader"
android:layout_weight=".10" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dimen96dp"
android:text="@string/settingsLabelsInListHint"
android:textColor="?attr/hintColor"
android:textSize="@dimen/dimen12sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/langFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
<TextView
android:id="@+id/tvLanguageHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsLanguageSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/tvLanguageSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsLanguageSelectedHeaderDefault"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
<TextView
android:id="@+id/helpTranslate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:background="?android:attr/selectableItemBackground"
android:paddingTop="@dimen/dimen12dp"
android:text="@string/settingsHelpTranslateText"
android:textColor="@color/lightBlue"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/label_title_frame"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen84dp"
android:text="@string/settingsLabelsInListHint"
android:textColor="?attr/hintColor"
android:textSize="@dimen/dimen12sp" />
</androidx.core.widget.NestedScrollView>
</RelativeLayout>
<LinearLayout
android:id="@+id/langFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/tvLanguageHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsLanguageSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<TextView
android:id="@+id/tvLanguageSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsLanguageSelectedHeaderDefault"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
</LinearLayout>
<TextView
android:id="@+id/helpTranslate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:background="?android:attr/selectableItemBackground"
android:paddingStart="@dimen/dimen40dp"
android:paddingTop="@dimen/dimen12dp"
android:paddingBottom="@dimen/dimen12dp"
android:paddingEnd="@dimen/dimen24dp"
android:layout_marginBottom="@dimen/dimen2dp"
android:text="@string/settingsHelpTranslateText"
android:textColor="@color/lightBlue"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,150 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen10dp"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
android:theme="@style/AppTheme.AppBarOverlay">
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/codeEditor"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/codeEditor"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:id="@+id/ceColorSelectionFrame"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:id="@+id/ceColorHeaderSelector"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/ceSyntaxHighlightColor"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/ceColorSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/themeSelectionSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
<LinearLayout
android:id="@+id/ceColorSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:layout_marginTop="@dimen/dimen8dp"
android:orientation="vertical">
</LinearLayout>
<TextView
android:id="@+id/ceColorHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ceSyntaxHighlightColor"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<LinearLayout
android:id="@+id/indentationSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/ceColorSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/themeSelectionSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
<TextView
android:id="@+id/indentationHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/ceIndentation"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
</LinearLayout>
<TextView
android:id="@+id/indentationSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsThemeTimeSelectedHint"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
<LinearLayout
android:id="@+id/indentationSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
</LinearLayout>
<TextView
android:id="@+id/indentationHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ceIndentation"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<LinearLayout
android:id="@+id/indentationTabsSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/indentationSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsThemeTimeSelectedHint"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
<TextView
android:id="@+id/indentationTabsHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/ceIndentationTabsWidth"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
</LinearLayout>
<TextView
android:id="@+id/indentationTabsSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsThemeTimeSelectedHint"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
<LinearLayout
android:id="@+id/indentationTabsSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
</LinearLayout>
<TextView
android:id="@+id/indentationTabsHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ceIndentationTabsWidth"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
</LinearLayout>
<TextView
android:id="@+id/indentationTabsSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsThemeTimeSelectedHint"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,252 +1,213 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen10dp"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
android:theme="@style/AppTheme.AppBarOverlay">
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/settingsGeneralHeader"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbarTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/settingsGeneralHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:id="@+id/setDefaultLinkHandler"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/generalDeepLinkDefaultScreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:layout_marginBottom="@dimen/dimen6dp"
android:text="@string/generalDeepLinkDefaultScreen"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/generalDeepLinkDefaultScreenHintText"
android:textColor="?attr/hintColor"
android:textSize="@dimen/dimen12sp"/>
<TextView
android:id="@+id/generalDeepLinkSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/none"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/homeScreenFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/homeScreenHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsHomeScreenHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<TextView
android:id="@+id/homeScreenSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsHomeScreenSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
</LinearLayout>
<RelativeLayout
android:id="@+id/customTabsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/customTabsHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen72dp"
android:text="@string/useCustomTabs"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switchTabs"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen24dp"
android:layout_alignParentEnd="true"
android:layout_gravity="end"
android:layout_toEndOf="@+id/customTabsHeader"
android:gravity="end"
android:paddingStart="@dimen/dimen0dp"
android:paddingEnd="@dimen/dimen24dp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/enableDraftsCommentsDeletion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:padding="@dimen/dimen16dp">
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/enableCommentsDeletionHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="100"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="90"
android:layout_marginStart="@dimen/dimen24dp"
android:text="@string/settingsEnableCommentsDeletionText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<LinearLayout
android:layout_width="wrap_content"
android:id="@+id/setDefaultLinkHandler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="10"
android:gravity="center_vertical|end"
android:layout_marginTop="@dimen/dimen8dp"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
<TextView
android:id="@+id/generalDeepLinkDefaultScreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen4dp"
android:text="@string/generalDeepLinkDefaultScreen"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/generalDeepLinkDefaultScreenHintText"
android:textColor="?attr/hintColor"
android:textSize="@dimen/dimen12sp" />
<TextView
android:id="@+id/generalDeepLinkSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/none"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/homeScreenFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
<TextView
android:id="@+id/homeScreenHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsHomeScreenHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/homeScreenSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsHomeScreenSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/customTabsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="horizontal">
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/commentsDeletionSwitch"
<TextView
android:id="@+id/customTabsHeader"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen32dp"
android:paddingStart="@dimen/dimen24dp"
android:paddingEnd="@dimen/dimen24dp" />
android:layout_height="wrap_content"
android:layout_weight=".90"
android:text="@string/useCustomTabs"
android:layout_marginTop="@dimen/dimen4dp"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switchTabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/useCustomTabs"
android:layout_weight=".10" />
</LinearLayout>
<LinearLayout
android:id="@+id/enableDraftsCommentsDeletion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".90"
android:text="@string/settingsEnableCommentsDeletionText"
android:layout_marginTop="@dimen/dimen4dp"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/commentsDeletionSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/settingsEnableCommentsDeletionText"
android:layout_weight=".10" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dimen96dp"
android:text="@string/settingsEnableCommentsDeletionHintText"
android:textColor="?attr/hintColor"
android:textSize="@dimen/dimen12sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/enableSendReports"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="horizontal">
<TextView
android:id="@+id/enableReportsHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".90"
android:text="@string/settingsEnableReportsText"
android:layout_marginTop="@dimen/dimen4dp"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/crashReportsSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/settingsEnableReportsText"
android:layout_weight=".10" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/enableCommentsDeletionHeader"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen72dp"
android:text="@string/settingsEnableCommentsDeletionHintText"
android:textColor="?attr/hintColor"
android:textSize="@dimen/dimen12sp" />
</androidx.core.widget.NestedScrollView>
</RelativeLayout>
<LinearLayout
android:id="@+id/enableSendReports"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:weightSum="100"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/enableReportsHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="90"
android:layout_marginStart="@dimen/dimen24dp"
android:text="@string/settingsEnableReportsText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="10"
android:gravity="center_vertical|end"
android:orientation="horizontal">
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/crashReportsSwitch"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen32dp"
android:paddingStart="@dimen/dimen24dp"
android:paddingEnd="@dimen/dimen24dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,219 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen10dp"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
android:theme="@style/AppTheme.AppBarOverlay"
tools:ignore="UnusedAttribute">
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close" />
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/pageTitleNotifications"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/pageTitleNotifications"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:id="@+id/enableNotificationsFrame"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:weightSum="100"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/enableNotificationsHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="90"
android:layout_marginStart="@dimen/dimen24dp"
android:text="@string/enableNotificationsHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="10"
android:gravity="center_vertical|end"
android:orientation="horizontal">
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/enableNotificationsMode"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen32dp"
android:paddingStart="@dimen/dimen24dp"
android:paddingEnd="@dimen/dimen24dp" />
<LinearLayout
android:id="@+id/enableNotificationsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/enableNotificationsHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".90"
android:text="@string/enableNotificationsHeaderText"
android:textColor="?attr/primaryTextColor"
android:layout_marginTop="@dimen/dimen4dp"
android:textSize="@dimen/dimen18sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/enableNotificationsMode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/enableNotificationsHeaderText"
android:layout_weight=".10" />
</LinearLayout>
<LinearLayout
android:id="@+id/pollingDelayFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen24dp"
android:orientation="vertical">
<TextView
android:id="@+id/pollingDelayHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/notificationsPollingHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/pollingDelaySelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pollingDelay15Minutes"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:id="@+id/pollingDelayFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/pollingDelayHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/notificationsPollingHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<TextView
android:id="@+id/pollingDelaySelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/pollingDelaySelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
<RelativeLayout
android:id="@+id/enableLightsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/enableLightsHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/enableLightsHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/enableLightsMode"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen24dp"
android:layout_alignParentEnd="true"
android:layout_gravity="end"
android:layout_toEndOf="@+id/enableLightsHeader"
android:gravity="end"
android:paddingStart="@dimen/dimen0dp"
android:paddingEnd="@dimen/dimen24dp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/chooseColorFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/chooseColorHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/chooseColorSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/chooseColorState"
style="?attr/materialCardViewFilledStyle"
android:layout_width="@dimen/dimen28dp"
android:layout_height="@dimen/dimen28dp"
android:layout_alignEnd="@id/chooseColorHeader"
android:layout_alignParentEnd="true"
android:layout_marginEnd="@dimen/dimen28dp"
android:gravity="end"
app:cardCornerRadius="@dimen/dimen16dp"
app:cardElevation="@dimen/dimen0dp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/enableVibrationFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/enableVibrationHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen72dp"
android:text="@string/enableVibrationHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/enableVibrationMode"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen24dp"
android:layout_alignParentEnd="true"
android:layout_gravity="end"
android:layout_toEndOf="@+id/enableVibrationHeader"
android:gravity="end"
android:paddingStart="@dimen/dimen0dp"
android:paddingEnd="@dimen/dimen24dp" />
</RelativeLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,196 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen10dp"
android:theme="@style/Widget.AppCompat.SearchView"
app:elevation="@dimen/dimen0dp">
android:background="?attr/primaryBackgroundColor"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutLargeStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:background="?attr/primaryBackgroundColor"
app:contentScrim="?attr/primaryBackgroundColor"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/dimen26dp"
android:layout_height="@dimen/dimen26dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen16dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
android:gravity="center_vertical"
android:src="@drawable/ic_close"/>
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:elevation="0dp"
android:layout_height="?attr/actionBarSize"
app:title="@string/settingsSecurityHeader"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:maxLines="1"
android:text="@string/settingsSecurityHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen20sp"/>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<RelativeLayout
android:id="@+id/biometricFrame"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:padding="@dimen/dimen16dp">
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:id="@+id/biometricHeader"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen72dp"
android:text="@string/settingsBiometricHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switchBiometric"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen24dp"
android:layout_alignParentEnd="true"
android:layout_gravity="end"
android:layout_toEndOf="@+id/biometricHeader"
android:gravity="end"
android:paddingStart="@dimen/dimen0dp"
android:paddingEnd="@dimen/dimen24dp" />
<LinearLayout
android:id="@+id/biometricFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
</RelativeLayout>
<TextView
android:id="@+id/biometricHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".90"
android:text="@string/settingsBiometricHeader"
android:layout_marginTop="@dimen/dimen4dp"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<LinearLayout
android:id="@+id/certsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switchBiometric"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/settingsBiometricHeader"
android:layout_weight=".10" />
<TextView
android:id="@+id/tvCertHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/settingsCertsSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="18sp"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/certsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="vertical">
<LinearLayout
android:id="@+id/cacheSizeDataSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/tvCertHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settingsCertsSelectorHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="18sp" />
<TextView
android:id="@+id/cacheSizeDataHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/cacheSizeDataSelectionHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
</LinearLayout>
<TextView
android:id="@+id/cacheSizeDataSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/cacheSizeDataSelectionSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
<LinearLayout
android:id="@+id/cacheSizeDataSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="vertical">
</LinearLayout>
<TextView
android:id="@+id/cacheSizeDataHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cacheSizeDataSelectionHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<LinearLayout
android:id="@+id/cacheSizeImagesSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/cacheSizeDataSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cacheSizeDataSelectionSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
<TextView
android:id="@+id/cacheSizeImagesHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/cacheSizeImagesSelectionHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
</LinearLayout>
<TextView
android:id="@+id/cacheSizeImagesSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/cacheSizeImagesSelectionSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
<LinearLayout
android:id="@+id/cacheSizeImagesSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="vertical">
</LinearLayout>
<TextView
android:id="@+id/cacheSizeImagesHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cacheSizeImagesSelectionHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
<LinearLayout
android:id="@+id/clearCacheSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen6dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="@dimen/dimen16dp">
<TextView
android:id="@+id/cacheSizeImagesSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cacheSizeImagesSelectionSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
<TextView
android:id="@+id/clearCacheHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/clearCacheSelectionHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp"/>
</LinearLayout>
<TextView
android:id="@+id/clearCacheSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen24dp"
android:layout_marginEnd="@dimen/dimen24dp"
android:text="@string/clearCacheSelectionSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp"/>
<LinearLayout
android:id="@+id/clearCacheSelectionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen32dp"
android:orientation="vertical">
</LinearLayout>
<TextView
android:id="@+id/clearCacheHeaderSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/clearCacheSelectionHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen18sp" />
</LinearLayout>
<TextView
android:id="@+id/clearCacheSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/clearCacheSelectionSelectedText"
android:textColor="?attr/selectedTextColor"
android:textSize="@dimen/dimen16sp" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -124,7 +124,6 @@
android:layout_marginBottom="@dimen/dimen8dp"
android:hint="@string/newIssueTitle"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
@ -151,7 +150,6 @@
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:textColorHint="?attr/hintColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
app:boxStrokeErrorColor="@color/darkRed"
app:hintTextColor="?attr/hintColor">

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical"
android:paddingTop="@dimen/dimen4dp"
android:paddingBottom="@dimen/dimen12dp">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/dimen12dp"
android:paddingEnd="@dimen/dimen12dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/issuesAttachmentsHeadFrame"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1"
android:padding="@dimen/dimen8dp">
<TextView
android:id="@+id/bottomSheetHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:text="@string/attachments"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen16sp" />
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
android:layout_width="@dimen/dimen28dp"
android:layout_height="@dimen/dimen4dp"
android:layout_gravity="start"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen16dp"
app:cardCornerRadius="@dimen/dimen24dp"
app:cardElevation="@dimen/dimen0dp">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/fabColor" />
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?attr/materialCardViewElevatedStyle"
app:cardCornerRadius="@dimen/dimen24dp"
android:layout_gravity="end"
android:layout_marginStart="@dimen/dimen4dp"
android:layout_marginEnd="@dimen/dimen4dp"
app:cardElevation="@dimen/dimen0dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/fabColor"
android:padding="@dimen/dimen8dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/add_attachment"
android:layout_width="@dimen/dimen24dp"
android:layout_height="@dimen/dimen24dp"
android:src="@drawable/ic_add"
android:contentDescription="@string/generalImgContentText"
app:tint="?attr/materialCardBackgroundColor" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_attachments"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen4dp"
android:padding="@dimen/dimen2dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/dimen32dp"
android:layout_gravity="center"
android:contentDescription="@string/generalImgContentText" />
</LinearLayout>

View File

@ -1,11 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".activities.RepoDetailActivity">
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:layout_width="match_parent"

View File

@ -73,12 +73,11 @@
android:textColorLink="@color/lightBlue"
android:textSize="@dimen/dimen16sp"/>
<View
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen24dp"
android:layout_marginBottom="@dimen/dimen24dp"
android:background="?attr/dividerColor"/>
android:layout_marginBottom="@dimen/dimen24dp" />
<LinearLayout
android:layout_width="match_parent"

View File

@ -101,85 +101,42 @@
android:layout_marginTop="@dimen/dimen20dp"
android:layout_marginBottom="@dimen/dimen0dp"
android:orientation="horizontal"
android:gravity="center"
android:baselineAligned="false">
<LinearLayout
android:id="@+id/followers_section"
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/metaInfoGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/profileTabFollowers"
android:textSize="@dimen/dimen14sp" />
<TextView
<Button
android:id="@+id/user_followers_count"
style="?attr/materialButtonToggleGroupStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textSize="@dimen/dimen14sp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
android:text="@string/profileTabFollowers" />
</LinearLayout>
<LinearLayout
android:id="@+id/following_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/profileTabFollowing"
android:textSize="@dimen/dimen14sp" />
<TextView
<Button
android:id="@+id/user_following_count"
style="?attr/materialButtonToggleGroupStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textSize="@dimen/dimen14sp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
android:text="@string/profileTabFollowing" />
</LinearLayout>
<LinearLayout
android:id="@+id/starred_repos_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:text="@string/starredRepos"
android:textSize="@dimen/dimen14sp" />
<TextView
<Button
android:id="@+id/user_starred_repos_count"
style="?attr/materialButtonToggleGroupStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:paddingTop="@dimen/dimen6dp"
android:textSize="@dimen/dimen14sp"
android:textStyle="bold"
android:textSize="@dimen/dimen14sp" />
android:text="@string/starredRepos" />
</LinearLayout>
</com.google.android.material.button.MaterialButtonToggleGroup>
</LinearLayout>

View File

@ -134,25 +134,17 @@
android:textColorLink="@color/lightBlue"
android:textSize="@dimen/dimen16sp"/>
<com.google.android.material.card.MaterialCardView
<org.mian.gitnex.helpers.languagestatistics.LanguageStatisticsBar
android:id="@+id/languages_statistic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/materialCardViewElevatedStyle"
android:backgroundTint="@android:color/transparent"
app:cardElevation="@dimen/dimen0dp">
<org.mian.gitnex.helpers.languagestatistics.LanguageStatisticsBar
android:id="@+id/languages_statistic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:thumbTint="@android:color/transparent"
android:clickable="false"
android:focusable="false"
android:enabled="false"
android:progressDrawable="@android:color/transparent"
android:visibility="gone" />
</com.google.android.material.card.MaterialCardView>
android:layout_height="@dimen/dimen22dp"
android:layout_marginTop="@dimen/dimen4dp"
android:thumbTint="@android:color/transparent"
android:clickable="false"
android:focusable="false"
android:enabled="false"
android:progressDrawable="@android:color/transparent"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
@ -160,110 +152,55 @@
android:layout_marginTop="@dimen/dimen20dp"
android:layout_marginBottom="@dimen/dimen20dp"
android:baselineAligned="false"
android:orientation="horizontal">
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:id="@+id/repoMetaStarsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:focusable="true"
android:clickable="true"
android:gravity="center"
android:orientation="vertical">
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/metaInfoGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/repoStargazersInMenu"
app:srcCompat="@drawable/ic_star_unfilled"/>
<TextView
<Button
android:id="@+id/repoMetaStars"
style="?attr/materialButtonToggleGroupStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp"/>
android:textSize="@dimen/dimen14sp"
android:textStyle="bold"
app:icon="@drawable/ic_star_unfilled"
android:text="@string/repoStars" />
</LinearLayout>
<LinearLayout
android:id="@+id/repoMetaPullRequestsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:focusable="true"
android:clickable="true"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/tabPullRequests"
app:srcCompat="@drawable/ic_pull_request"/>
<TextView
<Button
android:id="@+id/repoMetaPullRequests"
style="?attr/materialButtonToggleGroupStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp"/>
</LinearLayout>
android:textSize="@dimen/dimen14sp"
android:textStyle="bold"
app:icon="@drawable/ic_pull_request"
android:text="@string/repoStars" />
<LinearLayout
android:id="@+id/repoMetaForksFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:focusable="true"
android:clickable="true"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/infoTabRepoForksCount"
app:srcCompat="@drawable/ic_fork"/>
<TextView
<Button
android:id="@+id/repoMetaForks"
style="?attr/materialButtonToggleGroupStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp"/>
android:textSize="@dimen/dimen14sp"
android:textStyle="bold"
app:icon="@drawable/ic_fork"
android:text="@string/repoStars" />
</LinearLayout>
<LinearLayout
android:id="@+id/repoMetaWatchersFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:focusable="true"
android:clickable="true"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/repoWatchersInMenu"
app:srcCompat="@drawable/ic_watchers"/>
<TextView
<Button
android:id="@+id/repoMetaWatchers"
style="?attr/materialButtonToggleGroupStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp"/>
android:textSize="@dimen/dimen14sp"
android:textStyle="bold"
app:icon="@drawable/ic_watchers"
android:text="@string/repoStars" />
</LinearLayout>
</com.google.android.material.button.MaterialButtonToggleGroup>
</LinearLayout>
@ -425,15 +362,25 @@
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/repoAdditionalButton"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen54dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/dimen6dp"
android:layout_marginBottom="@dimen/dimen20dp"
android:text="@string/infoShowMoreInformation"
android:textColor="?attr/materialCardBackgroundColor"/>
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/moreInfoFrame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen12dp"
android:layout_gravity="center">
<Button
android:id="@+id/repoAdditionalButton"
style="?attr/materialButtonToggleGroupStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/dimen14sp"
android:textStyle="bold"
app:icon="@drawable/ic_info"
android:text="@string/infoMoreInformation" />
</com.google.android.material.button.MaterialButtonToggleGroup>
</LinearLayout>

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/fileFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/dimen4dp"
android:paddingBottom="@dimen/dimen4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/materialCardViewElevatedStyle"
app:cardElevation="@dimen/dimen0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/dimen12dp"
android:orientation="horizontal">
<com.google.android.material.card.MaterialCardView
android:id="@+id/attachmentViewFrame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?attr/materialCardViewElevatedStyle"
android:visibility="gone"
android:layout_marginEnd="@dimen/dimen8dp"
app:cardElevation="@dimen/dimen0dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/materialCardBackgroundColor"
android:orientation="horizontal">
<ImageView
android:id="@+id/attachment"
android:layout_width="@dimen/dimen36dp"
android:layout_height="@dimen/dimen36dp"
android:contentDescription="@string/generalImgContentText" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:id="@+id/filename_section"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".90"
android:layout_gravity="center_vertical"
android:layout_marginEnd="@dimen/dimen48dp"
android:orientation="vertical">
<TextView
android:id="@+id/filename"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/defaultFilename"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp" />
</LinearLayout>
<ImageView
android:id="@+id/delete_attachment"
android:layout_width="@dimen/dimen20dp"
android:layout_height="@dimen/dimen20dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/dimen0dp"
android:contentDescription="@string/generalImgContentText"
android:src="@drawable/ic_delete" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>

View File

@ -2,7 +2,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/relativeLayoutFrameIssuesList"
android:id="@+id/dashboardLayoutCardsFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/dimen4dp"
@ -10,6 +10,7 @@
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/materialCardViewElevatedStyle"

View File

@ -35,8 +35,15 @@
android:layout_height="wrap_content"
android:background="?attr/materialCardBackgroundColor"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="@dimen/dimen12dp">
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/materialCardBackgroundColor"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="@dimen/dimen12dp">
<LinearLayout
android:layout_width="match_parent"
@ -64,8 +71,8 @@
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginLeft="@dimen/dimen16dp"
android:layout_marginRight="@dimen/dimen16dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
@ -77,7 +84,7 @@
android:ellipsize="middle"
android:singleLine="true"
android:textColor="?attr/primaryTextColor"
android:textSize="14sp"
android:textSize="@dimen/dimen14sp"
android:textStyle="bold" />
<TextView
@ -87,7 +94,8 @@
android:ellipsize="end"
android:singleLine="true"
android:textColor="?attr/hintColor"
android:textSize="12sp" />
android:textSize="@dimen/dimen12sp" />
</LinearLayout>
<ImageView
@ -111,16 +119,43 @@
android:textColor="?attr/primaryTextColor"
android:textColorLink="@color/lightBlue"
android:textIsSelectable="true"
android:textSize="14sp" />
android:textSize="@dimen/dimen14sp" />
<LinearLayout
android:id="@+id/commentReactionBadges"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginTop="@dimen/dimen16dp"
android:orientation="horizontal"
android:visibility="gone" />
</LinearLayout>
<LinearLayout
android:id="@+id/attachmentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/materialCardBackgroundColor"
android:foreground="?android:attr/selectableItemBackground"
android:visibility="gone"
android:orientation="vertical">
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen4dp" />
<LinearLayout
android:id="@+id/attachmentsView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/dimen12dp"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -62,7 +62,7 @@
<View
android:id="@+id/spacer_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen8dp" />
<LinearLayout
@ -71,40 +71,45 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="@dimen/dimen18dp"
android:layout_height="@dimen/dimen18dp"
android:layout_marginStart="@dimen/dimen0dp"
android:layout_marginEnd="@dimen/dimen6dp"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_trending"
app:tint="?attr/iconsColor" />
<LinearLayout
android:id="@+id/repo_info_counter_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".90"
android:orientation="horizontal">
<TextView
android:id="@+id/most_visited"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp"
tools:text="@string/repoStars" />
<ImageView
android:layout_width="@dimen/dimen18dp"
android:layout_height="@dimen/dimen18dp"
android:layout_marginStart="@dimen/dimen0dp"
android:layout_marginEnd="@dimen/dimen6dp"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_trending"
app:tint="?attr/iconsColor" />
<TextView
android:id="@+id/most_visited"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textColor="?attr/primaryTextColor"
android:textSize="@dimen/dimen14sp"
tools:text="@string/repoStars" />
</LinearLayout>
<LinearLayout
android:id="@+id/repo_info_end_frame"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen10dp"
android:gravity="center_vertical|end"
android:orientation="horizontal"
android:paddingStart="@dimen/dimen6dp"
android:paddingEnd="@dimen/dimen0dp">
android:layout_weight=".10"
android:gravity="end"
android:orientation="horizontal">
<ImageView
android:id="@+id/reset_counter"
android:layout_width="@dimen/dimen18dp"
android:layout_height="@dimen/dimen18dp"
android:layout_marginStart="@dimen/dimen16dp"
android:layout_marginEnd="@dimen/dimen2dp"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_delete"
app:tint="?attr/iconsColor" />

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/addAccount"
android:orderInCategory="0"
android:title="@string/addNewAccountText"
app:showAsAction="ifRoom" />
</menu>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/attachment"
android:icon="@drawable/ic_attachment"
android:orderInCategory="0"
android:title="@string/attachment"
app:showAsAction="ifRoom" />
<item
android:id="@+id/markdown"
android:icon="@drawable/ic_markdown"
android:orderInCategory="1"
android:title="@string/strMarkdown"
app:showAsAction="ifRoom" />
<item
android:id="@+id/create"
android:title="@string/newCreateButtonCopy"
android:orderInCategory="2"
android:contentDescription="@string/newCreateButtonCopy"
app:showAsAction="ifRoom" />
</menu>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/create"
android:orderInCategory="0"
android:title="@string/newCreateButtonCopy"
android:contentDescription="@string/newCreateButtonCopy"
app:showAsAction="ifRoom" />
<item
android:id="@+id/update"
android:orderInCategory="1"
android:title="@string/newUpdateButtonCopy"
android:contentDescription="@string/newUpdateButtonCopy"
app:showAsAction="ifRoom" />
</menu>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/markdown"
android:icon="@drawable/ic_markdown"
android:orderInCategory="0"
android:title="@string/strMarkdown"
app:showAsAction="ifRoom" />
<item
android:id="@+id/create"
android:orderInCategory="1"
android:title="@string/newCreateButtonCopy"
android:contentDescription="@string/newCreateButtonCopy" />
<item
android:id="@+id/create_tag"
android:orderInCategory="2"
android:title="@string/create_tag"
android:contentDescription="@string/create_tag" />
</menu>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/create"
android:title="@string/newCreateButtonCopy"
android:orderInCategory="0"
android:contentDescription="@string/newCreateButtonCopy"
app:showAsAction="ifRoom" />
<item
android:id="@+id/update"
android:title="@string/menuEditText"
android:orderInCategory="1"
android:contentDescription="@string/newCreateButtonCopy"
app:showAsAction="ifRoom" />
<item
android:id="@+id/delete"
android:title="@string/menuDeleteText"
android:orderInCategory="2"
android:contentDescription="@string/menuDeleteText"
app:showAsAction="ifRoom" />
</menu>

View File

@ -5,7 +5,6 @@
<item
android:id="@+id/save"
android:icon="@drawable/ic_save"
android:orderInCategory="1"
android:title="@string/saveButton"
app:showAsAction="ifRoom"/>

View File

@ -11,6 +11,7 @@
<dimen name="dimen16dp">16dp</dimen>
<dimen name="dimen18dp">18dp</dimen>
<dimen name="dimen20dp">20dp</dimen>
<dimen name="dimen22dp">22dp</dimen>
<dimen name="dimen24dp">24dp</dimen>
<dimen name="dimen26dp">26dp</dimen>
<dimen name="dimen28dp">28dp</dimen>

View File

@ -118,4 +118,191 @@
<item>@string/zoomOut</item>
<item>@string/none</item>
</string-array>
<string-array name="notificationsPollingDelay">
<item>@string/pollingDelay15Minutes</item>
<item>@string/pollingDelay30Minutes</item>
<item>@string/pollingDelay45Minutes</item>
<item>@string/pollingDelay1Hour</item>
</string-array>
<string-array name="licenses">
<item>0BSD</item>
<item>AAL</item>
<item>ADSL</item>
<item>AFL-1.1</item>
<item>AFL-1.1</item>
<item>AFL-2.0</item>
<item>AFL-3.0</item>
<item>AGPL-1.0-only</item>
<item>AGPL-1.0-or-later</item>
<item>AGPL-3.0-only</item>
<item>AGPL-3.0-or-later</item>
<item>AML</item>
<item>APL-1.0</item>
<item>APSL-1.0</item>
<item>APSL-2.0</item>
<item>Adobe-2006</item>
<item>Aladdin</item>
<item>Apache-1.0</item>
<item>Apache-1.1</item>
<item>Apache-2.0</item>
<item>Artistic-1.0</item>
<item>Artistic-2.0</item>
<item>BSD-1-Clause</item>
<item>BSD-2-Clause</item>
<item>BSD-2-Clause-Patent</item>
<item>BSD-2-Clause-Views</item>
<item>BSD-3-Clause</item>
<item>BSD-3-Clause-Attribution</item>
<item>BSD-3-Clause-Clear</item>
<item>BSD-3-Clause-LBNL</item>
<item>BSD-3-Clause-Modification</item>
<item>BSD-3-Clause-No-Military-License</item>
<item>BSD-3-Clause-No-Nuclear-License</item>
<item>BSD-3-Clause-No-Nuclear-License-2014</item>
<item>BSD-3-Clause-No-Nuclear-Warranty</item>
<item>BSD-3-Clause-Open-MPI</item>
<item>BSD-3-Clause-Sun</item>
<item>BSD-4-Clause-Shortened</item>
<item>BSD-4-Clause-UC</item>
<item>BSD-4.3RENO</item>
<item>BSD-4.3TAHOE</item>
<item>BSD-Advertising-Acknowledgement</item>
<item>BSD-Attribution-HPND-disclaimer</item>
<item>BSD-Protection</item>
<item>BSD-Source-Code</item>
<item>BSD-Systemics</item>
<item>BitTorrent-1.0</item>
<item>BitTorrent-1.1</item>
<item>CC-BY-1.0</item>
<item>CC-BY-2.0</item>
<item>CC-BY-2.5</item>
<item>CC-BY-2.5-AU</item>
<item>CC-BY-3.0</item>
<item>CC-BY-3.0-AT</item>
<item>CC-BY-3.0-DE</item>
<item>CC-BY-4.0</item>
<item>CC-BY-NC-1.0</item>
<item>CC-BY-NC-2.0</item>
<item>CC-BY-NC-2.5</item>
<item>CC-BY-NC-3.0</item>
<item>CC-BY-NC-4.0</item>
<item>Community-Spec-1.0</item>
<item>Cube</item>
<item>D-FSL-1.0</item>
<item>DL-DE-BY-2.0</item>
<item>ECL-1.0</item>
<item>ECL-2.0</item>
<item>EFL-1.0</item>
<item>EFL-2.0</item>
<item>Elastic-2.0</item>
<item>FreeBSD-DOC</item>
<item>GD</item>
<item>GFDL-1.1-only</item>
<item>GFDL-1.1-or-later</item>
<item>GFDL-1.2-only</item>
<item>GFDL-1.2-or-later</item>
<item>GFDL-1.3-only</item>
<item>GFDL-1.3-or-later</item>
<item>GPL-1.0-only</item>
<item>GPL-1.0-or-later</item>
<item>GPL-2.0-only</item>
<item>GPL-2.0-or-later</item>
<item>GPL-3.0-interface-exception</item>
<item>GPL-3.0-only</item>
<item>GPL-3.0-or-later</item>
<item>GPL-CC-1.0</item>
<item>GStreamer-exception-2008</item>
<item>Glide</item>
<item>HP-1989</item>
<item>IBM-pibs</item>
<item>ICU</item>
<item>IPL-1.0</item>
<item>ImageMagick</item>
<item>Intel</item>
<item>Intel-ACPI</item>
<item>Interbase-1.0</item>
<item>JSON</item>
<item>LAL-1.3</item>
<item>LGPL-2.0-only</item>
<item>LGPL-2.0-or-later</item>
<item>LGPL-2.1-only</item>
<item>LGPL-2.1-or-later</item>
<item>LGPL-3.0-only</item>
<item>LGPL-3.0-or-later</item>
<item>LGPLLR</item>
<item>LLGPL</item>
<item>LPL-1.0</item>
<item>LPL-1.02</item>
<item>LPPL-1.0</item>
<item>LPPL-1.3a</item>
<item>LPPL-1.3c</item>
<item>Libpng</item>
<item>Linux-OpenIB</item>
<item>MIT</item>
<item>MIT-0</item>
<item>MIT-CMU</item>
<item>MIT-Festival</item>
<item>MIT-Modern-Variant</item>
<item>MIT-Wu</item>
<item>MIT-advertising</item>
<item>MIT-open-group</item>
<item>MPL-1.0</item>
<item>MPL-2.0</item>
<item>MirOS</item>
<item>NASA-1.3</item>
<item>NTP</item>
<item>Nokia</item>
<item>OCLC-2.0</item>
<item>OFL-1.0</item>
<item>OFL-1.1</item>
<item>OLDAP-1.1</item>
<item>OLDAP-2.0</item>
<item>OLDAP-2.8</item>
<item>OML</item>
<item>OSL-1.0</item>
<item>OSL-2.0</item>
<item>OSL-3.0</item>
<item>OpenSSL</item>
<item>PHP-3.0</item>
<item>PSF-2.0</item>
<item>PostgreSQL</item>
<item>Python-2.0</item>
<item>QPL-1.0</item>
<item>Qt-GPL-exception-1.0</item>
<item>Qt-GPL-exception-1.1</item>
<item>RPL-1.1</item>
<item>RPL-1.5</item>
<item>Ruby</item>
<item>SGI-B-1.0</item>
<item>SGI-B-2.0</item>
<item>SSH-OpenSSH</item>
<item>Sendmail</item>
<item>TCL</item>
<item>UnixCrypt</item>
<item>Unlicense</item>
<item>Vim</item>
<item>W3C</item>
<item>WTFPL</item>
<item>X11</item>
<item>XFree86-1.1</item>
<item>Xdebug-1.03</item>
<item>Xerox</item>
<item>YPL-1.0</item>
<item>ZPL-1.1</item>
<item>ZPL-2.0</item>
<item>Zed</item>
<item>Zimbra-1.4</item>
<item>Zlib</item>
<item>bzip2-1.0.6</item>
<item>copyleft-next-0.3.1</item>
<item>curl</item>
<item>gnuplot</item>
<item>libpng-2.0</item>
<item>libselinux-1.0</item>
<item>w3m</item>
<item>xpp</item>
<item>zlib-acknowledgement</item>
</string-array>
</resources>

View File

@ -72,6 +72,10 @@
<string name="newRepoDescTintCopy">Repository Description</string>
<string name="newRepoPrivateCopy">Private</string>
<string name="newRepoOwner">Owner</string>
<string name="newRepoIssueLabels">Issue Labels</string>
<string name="advanced" translatable="false">Advanced</string>
<string name="defaultText" translatable="false">Default</string>
<string name="setAsTemplate">Make repository a template</string>
<string name="newOrgTintCopy">Organization Name</string>
<string name="newOrgDescTintCopy">Organization Description</string>
@ -103,6 +107,7 @@
<string name="repoCreated">Repository created successfully</string>
<string name="repoExistsError">Repository of this name already exists under selected Owner</string>
<string name="repoOwnerError">Select owner for the repository</string>
<string name="repoDefaultBranchError">The default branch must not be empty</string>
<string name="orgNameErrorEmpty">Organization name is empty</string>
<string name="orgNameErrorInvalid">Organization name is not valid, [a&#8211;z A&#8211;Z 0&#8211;9 &#8211; _]</string>
@ -144,7 +149,6 @@
<string name="infoTabRepoUpdatedAt">Last Updated</string>
<string name="infoTabRepoZero" translatable="false">0</string>
<string name="infoShowMoreInformation">Show More Information</string>
<string name="infoMoreInformation">More Information</string>
<string name="timeAtText">at</string>
@ -524,6 +528,8 @@
<string name="reset">Reset</string>
<string name="beta">BETA</string>
<string name="none">None</string>
<string name="main">main</string>
<string name="license">License</string>
<!-- generic copy -->
<string name="exploreUsers">Explore users</string>
@ -541,8 +547,7 @@
<string name="versionUnknown">No Gitea detected!</string>
<string name="versionAlertDialogHeader">Unsupported Version of Gitea</string>
<string name="loginViaPassword">Username / Password</string>
<string name="loginMethodText">Choose your preferred login method to access your account. Token is more secure!</string>
<string name="loginViaPassword">Basic Auth</string>
<string name="unauthorizedApiError">Instance has returned an error - Unauthorized. Check your credentials and try again</string>
<string name="loginTokenError">Token is required</string>
@ -651,7 +656,7 @@
<string name="removeAccountPopupTitle">Remove Account</string>
<string name="removeAccountPopupMessage">Are you sure you want to remove this account from the app?\n\nThis will remove all the data related to this account on the app only.</string>
<string name="addNewAccount">New Account</string>
<string name="addNewAccountText">Add New Account</string>
<string name="addNewAccountText">Add Account</string>
<string name="accountAlreadyExistsError">Account already exists in the app</string>
<string name="accountAddedMessage">Account added successfully</string>
<string name="switchAccountSuccess">Switched to account : %1$s@%2$s</string>
@ -660,14 +665,17 @@
<string name="pageTitleNotifications">Notifications</string>
<string name="noDataNotifications">All caught up 🚀</string>
<string name="notificationsPollingHeaderText">Notifications Polling Delay</string>
<string name="pollingDelaySelectedText">%d Minutes</string>
<string name="pollingDelay15Minutes">15 Minutes</string>
<string name="pollingDelay30Minutes">30 Minutes</string>
<string name="pollingDelay45Minutes">45 Minutes</string>
<string name="pollingDelay1Hour">1 Hour</string>
<string name="pollingDelayDialogHeaderText">Select Polling Delay</string>
<string name="pollingDelayDialogDescriptionText">Choose a minutely delay in which GitNex tries to poll new notifications</string>
<string name="markAsRead">Mark Read</string>
<string name="markAsUnread">Mark Unread</string>
<string name="pinNotification">Pin</string>
<string name="markedNotificationsAsRead">Successfully marked all notifications as read</string>
<string name="notificationsHintText">Polling delay, light, vibration</string>
<string name="notificationsHintText">Polling delay</string>
<string name="enableNotificationsHeaderText">Enable Notifications</string>
<string name="enableLightsHeaderText">Enable Light</string>
<string name="enableVibrationHeaderText">Enable Vibration</string>
@ -681,6 +689,7 @@
<item quantity="one">You have %s new notification</item>
<item quantity="other">You have %s new notifications</item>
</plurals>
<string name="openAppSettings">To receive notifications, you must enable notifications for GitNex. Tap Open to access your phone settings and enable notifications.</string>
<string name="isRead">Read</string>
<string name="isUnread">Unread</string>
@ -865,6 +874,7 @@
<string name="timelineRefIssue">%1$s referenced this issue in #%2$d %3$s</string>
<string name="timelineRefPr">%1$s referenced this pull request in #%2$d %3$s</string>
<string name="timelineStatusRefIssue"><![CDATA[%1$s referenced this issue from a <font color=\'%2$d\'>%3$s</font> %4$s]]></string>
<string name="timelineReviewLeftComment">%1$s left a comment: %2$s %3$s</string>
<string name="commitStatuses">Statuses</string>
<string name="statusNoUrl">This status has no linked target URL.</string>
@ -875,4 +885,33 @@
<string name="lang_percentage" translatable="false">%s%%</string>
<string name="dashboard">Dashboard</string>
<string name="createdRepository">created repository</string>
<string name="renamedRepository">renamed repository from %1$s to</string>
<string name="starredRepository">starred</string>
<string name="transferredRepository">transferred repository %1$s to</string>
<string name="createdBranch">created branch %1$s in</string>
<string name="pushedTo">pushed to %1$s at</string>
<string name="openedIssue">opened issue</string>
<string name="commentedOnIssue">commented on issue</string>
<string name="closedIssue">closed issue</string>
<string name="reopenedIssue">reopened issue</string>
<string name="createdPR">created pull request</string>
<string name="closedPR">closed pull request</string>
<string name="reopenedPR">reopened pull request</string>
<string name="mergedPR">merged pull request</string>
<string name="approved">approved</string>
<string name="suggestedChanges">suggested changes for</string>
<string name="commentedOnPR">commented on pull request</string>
<string name="autoMergePR">automatically merged pull request</string>
<string name="deletedBranch">deleted branch %1$s at</string>
<string name="pushedTag">pushed tag %1$s to</string>
<string name="deletedTag">deleted tag %1$s from</string>
<string name="releasedBranch">released %1$s at</string>
<string name="syncedCommits">synced commits to %1$s at</string>
<string name="syncedRefs">synced new reference %1$s to</string>
<string name="syncedDeletedRefs">synced and deleted reference %1$s at</string>
<string name="attachment">Attachment</string>
<string name="attachments">Attachments</string>
<string name="attachmentsSaveError">An issue was created but cannot process attachments at this time. Check the server logs for more details.</string>
</resources>

View File

@ -7,7 +7,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.0.2'
classpath 'com.android.tools.build:gradle:8.1.2'
}
}
@ -19,6 +19,6 @@ allprojects {
}
}
task clean(type: Delete) {
tasks.register('clean', Delete) {
delete rootProject.buildDir
}