mirror of
https://codeberg.org/gitnex/GitNex.git
synced 2024-12-16 15:48:13 +08:00
Update user avatar (#1349)
Closes #552 Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1349 Co-authored-by: M M Arif <mmarif@swatian.com> Co-committed-by: M M Arif <mmarif@swatian.com>
This commit is contained in:
parent
7c435e4f34
commit
254779a324
@ -8,8 +8,8 @@ android {
|
|||||||
applicationId "org.mian.gitnex"
|
applicationId "org.mian.gitnex"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 34
|
targetSdkVersion 34
|
||||||
versionCode 540
|
versionCode 545
|
||||||
versionName "5.4.0"
|
versionName "5.5.0-dev"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
compileSdk 34
|
compileSdk 34
|
||||||
@ -71,9 +71,9 @@ dependencies {
|
|||||||
implementation 'com.google.code.gson:gson:2.10.1'
|
implementation 'com.google.code.gson:gson:2.10.1'
|
||||||
implementation "com.squareup.picasso:picasso:2.71828"
|
implementation "com.squareup.picasso:picasso:2.71828"
|
||||||
implementation 'com.github.ramseth001:TextDrawable:1.1.3'
|
implementation 'com.github.ramseth001:TextDrawable:1.1.3'
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.11.0'
|
||||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
implementation 'com.squareup.retrofit2:converter-gson:2.11.0'
|
||||||
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
|
implementation 'com.squareup.retrofit2:converter-scalars:2.11.0'
|
||||||
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.12'
|
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.12'
|
||||||
implementation 'org.ocpsoft.prettytime:prettytime:5.0.7.Final'
|
implementation 'org.ocpsoft.prettytime:prettytime:5.0.7.Final'
|
||||||
implementation "com.github.skydoves:colorpickerview:2.3.0"
|
implementation "com.github.skydoves:colorpickerview:2.3.0"
|
||||||
|
@ -54,6 +54,7 @@ import org.mian.gitnex.fragments.RepositoriesFragment;
|
|||||||
import org.mian.gitnex.fragments.SettingsFragment;
|
import org.mian.gitnex.fragments.SettingsFragment;
|
||||||
import org.mian.gitnex.fragments.StarredRepositoriesFragment;
|
import org.mian.gitnex.fragments.StarredRepositoriesFragment;
|
||||||
import org.mian.gitnex.fragments.WatchedRepositoriesFragment;
|
import org.mian.gitnex.fragments.WatchedRepositoriesFragment;
|
||||||
|
import org.mian.gitnex.fragments.profile.DetailFragment;
|
||||||
import org.mian.gitnex.helpers.AlertDialogs;
|
import org.mian.gitnex.helpers.AlertDialogs;
|
||||||
import org.mian.gitnex.helpers.AppDatabaseSettings;
|
import org.mian.gitnex.helpers.AppDatabaseSettings;
|
||||||
import org.mian.gitnex.helpers.AppUtil;
|
import org.mian.gitnex.helpers.AppUtil;
|
||||||
@ -298,10 +299,6 @@ public class MainActivity extends BaseActivity
|
|||||||
.setVisible(false);
|
.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getAccount().requiresVersion("1.14.0")) {
|
|
||||||
navigationView.getMenu().findItem(R.id.nav_my_issues).setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getAccount().requiresVersion("1.20.0")) {
|
if (getAccount().requiresVersion("1.20.0")) {
|
||||||
navigationView.getMenu().findItem(R.id.nav_dashboard).setVisible(true);
|
navigationView.getMenu().findItem(R.id.nav_dashboard).setVisible(true);
|
||||||
}
|
}
|
||||||
@ -586,6 +583,10 @@ public class MainActivity extends BaseActivity
|
|||||||
this.overridePendingTransition(0, 0);
|
this.overridePendingTransition(0, 0);
|
||||||
refActivity = false;
|
refActivity = false;
|
||||||
}
|
}
|
||||||
|
if (DetailFragment.refProfile) {
|
||||||
|
loadUserInfo();
|
||||||
|
DetailFragment.refProfile = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setActionBarTitle(String title) {
|
public void setActionBarTitle(String title) {
|
||||||
|
@ -71,7 +71,7 @@ public class AttachmentsAdapter extends RecyclerView.Adapter<AttachmentsAdapter.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewHolder extends RecyclerView.ViewHolder {
|
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
public TextView filename;
|
public TextView filename;
|
||||||
public ImageView delete;
|
public ImageView delete;
|
||||||
|
@ -34,7 +34,6 @@ import org.mian.gitnex.helpers.ColorInverter;
|
|||||||
import org.mian.gitnex.helpers.LabelWidthCalculator;
|
import org.mian.gitnex.helpers.LabelWidthCalculator;
|
||||||
import org.mian.gitnex.helpers.RoundedTransformation;
|
import org.mian.gitnex.helpers.RoundedTransformation;
|
||||||
import org.mian.gitnex.helpers.TimeHelper;
|
import org.mian.gitnex.helpers.TimeHelper;
|
||||||
import org.mian.gitnex.helpers.TinyDB;
|
|
||||||
import org.mian.gitnex.helpers.contexts.IssueContext;
|
import org.mian.gitnex.helpers.contexts.IssueContext;
|
||||||
import org.mian.gitnex.helpers.contexts.RepositoryContext;
|
import org.mian.gitnex.helpers.contexts.RepositoryContext;
|
||||||
|
|
||||||
@ -44,7 +43,6 @@ import org.mian.gitnex.helpers.contexts.RepositoryContext;
|
|||||||
public class ExploreIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
public class ExploreIssuesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final TinyDB tinyDb;
|
|
||||||
private List<Issue> searchedList;
|
private List<Issue> searchedList;
|
||||||
private OnLoadMoreListener loadMoreListener;
|
private OnLoadMoreListener loadMoreListener;
|
||||||
private boolean isLoading = false, isMoreDataAvailable = true;
|
private boolean isLoading = false, isMoreDataAvailable = true;
|
||||||
@ -52,7 +50,6 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter<RecyclerView.View
|
|||||||
public ExploreIssuesAdapter(List<Issue> dataList, Context ctx) {
|
public ExploreIssuesAdapter(List<Issue> dataList, Context ctx) {
|
||||||
this.context = ctx;
|
this.context = ctx;
|
||||||
this.searchedList = dataList;
|
this.searchedList = dataList;
|
||||||
this.tinyDb = TinyDB.getInstance(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull @Override
|
@NonNull @Override
|
||||||
|
@ -1,18 +1,28 @@
|
|||||||
package org.mian.gitnex.fragments.profile;
|
package org.mian.gitnex.fragments.profile;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import okhttp3.ResponseBody;
|
import okhttp3.ResponseBody;
|
||||||
import org.gitnex.tea4j.v2.models.Repository;
|
import org.gitnex.tea4j.v2.models.Repository;
|
||||||
|
import org.gitnex.tea4j.v2.models.UpdateUserAvatarOption;
|
||||||
import org.gitnex.tea4j.v2.models.User;
|
import org.gitnex.tea4j.v2.models.User;
|
||||||
import org.gitnex.tea4j.v2.models.UserSettings;
|
import org.gitnex.tea4j.v2.models.UserSettings;
|
||||||
import org.gitnex.tea4j.v2.models.UserSettingsOptions;
|
import org.gitnex.tea4j.v2.models.UserSettingsOptions;
|
||||||
@ -21,6 +31,7 @@ import org.mian.gitnex.activities.BaseActivity;
|
|||||||
import org.mian.gitnex.activities.ProfileActivity;
|
import org.mian.gitnex.activities.ProfileActivity;
|
||||||
import org.mian.gitnex.clients.PicassoService;
|
import org.mian.gitnex.clients.PicassoService;
|
||||||
import org.mian.gitnex.clients.RetrofitClient;
|
import org.mian.gitnex.clients.RetrofitClient;
|
||||||
|
import org.mian.gitnex.databinding.CustomEditAvatarDialogBinding;
|
||||||
import org.mian.gitnex.databinding.CustomEditProfileBinding;
|
import org.mian.gitnex.databinding.CustomEditProfileBinding;
|
||||||
import org.mian.gitnex.databinding.FragmentProfileDetailBinding;
|
import org.mian.gitnex.databinding.FragmentProfileDetailBinding;
|
||||||
import org.mian.gitnex.helpers.AlertDialogs;
|
import org.mian.gitnex.helpers.AlertDialogs;
|
||||||
@ -29,7 +40,6 @@ import org.mian.gitnex.helpers.ClickListener;
|
|||||||
import org.mian.gitnex.helpers.Markdown;
|
import org.mian.gitnex.helpers.Markdown;
|
||||||
import org.mian.gitnex.helpers.RoundedTransformation;
|
import org.mian.gitnex.helpers.RoundedTransformation;
|
||||||
import org.mian.gitnex.helpers.TimeHelper;
|
import org.mian.gitnex.helpers.TimeHelper;
|
||||||
import org.mian.gitnex.helpers.TinyDB;
|
|
||||||
import org.mian.gitnex.helpers.Toasty;
|
import org.mian.gitnex.helpers.Toasty;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
@ -41,13 +51,17 @@ public class DetailFragment extends Fragment {
|
|||||||
|
|
||||||
private static final String usernameBundle = "";
|
private static final String usernameBundle = "";
|
||||||
Locale locale;
|
Locale locale;
|
||||||
TinyDB tinyDb;
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private FragmentProfileDetailBinding binding;
|
private FragmentProfileDetailBinding binding;
|
||||||
private String username;
|
private String username;
|
||||||
private CustomEditProfileBinding customEditProfileBinding;
|
private CustomEditProfileBinding customEditProfileBinding;
|
||||||
|
private CustomEditAvatarDialogBinding customEditAvatarDialogBinding;
|
||||||
private MaterialAlertDialogBuilder materialAlertDialogBuilder;
|
private MaterialAlertDialogBuilder materialAlertDialogBuilder;
|
||||||
private AlertDialog dialogEditSettings;
|
private AlertDialog dialogEditSettings;
|
||||||
|
private AlertDialog dialogEditAvatar;
|
||||||
|
private int imgRadius;
|
||||||
|
private static Uri avatarUri = null;
|
||||||
|
public static boolean refProfile = false;
|
||||||
|
|
||||||
public DetailFragment() {}
|
public DetailFragment() {}
|
||||||
|
|
||||||
@ -73,8 +87,8 @@ public class DetailFragment extends Fragment {
|
|||||||
|
|
||||||
binding = FragmentProfileDetailBinding.inflate(inflater, container, false);
|
binding = FragmentProfileDetailBinding.inflate(inflater, container, false);
|
||||||
context = getContext();
|
context = getContext();
|
||||||
tinyDb = TinyDB.getInstance(context);
|
|
||||||
locale = getResources().getConfiguration().locale;
|
locale = getResources().getConfiguration().locale;
|
||||||
|
imgRadius = AppUtil.getPixelsFromDensity(context, 3);
|
||||||
|
|
||||||
getProfileDetail(username);
|
getProfileDetail(username);
|
||||||
getProfileRepository(username);
|
getProfileRepository(username);
|
||||||
@ -94,21 +108,121 @@ public class DetailFragment extends Fragment {
|
|||||||
((ProfileActivity) requireActivity()).viewPager.setCurrentItem(2));
|
((ProfileActivity) requireActivity()).viewPager.setCurrentItem(2));
|
||||||
|
|
||||||
if (username.equals(((BaseActivity) context).getAccount().getAccount().getUserName())) {
|
if (username.equals(((BaseActivity) context).getAccount().getAccount().getUserName())) {
|
||||||
binding.editProfile.setVisibility(View.VISIBLE);
|
binding.metaProfile.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
binding.editProfile.setVisibility(View.GONE);
|
binding.metaProfile.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.editProfile.setOnClickListener(
|
binding.updateProfile.setOnClickListener(
|
||||||
editProfileSettings -> {
|
editProfileSettings -> {
|
||||||
customEditProfileBinding =
|
customEditProfileBinding =
|
||||||
CustomEditProfileBinding.inflate(LayoutInflater.from(context));
|
CustomEditProfileBinding.inflate(LayoutInflater.from(context));
|
||||||
showEditProfileDialog();
|
showEditProfileDialog();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
binding.updateAvatar.setOnClickListener(updateAvatar -> openFileAttachment());
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onDestroy() {
|
||||||
|
avatarUri = null;
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivityResultLauncher<Intent> activityForAvatarUpdate =
|
||||||
|
registerForActivityResult(
|
||||||
|
new ActivityResultContracts.StartActivityForResult(),
|
||||||
|
result -> {
|
||||||
|
if (result.getResultCode() == Activity.RESULT_OK) {
|
||||||
|
Intent data = result.getData();
|
||||||
|
assert data != null;
|
||||||
|
avatarUri = data.getData();
|
||||||
|
if (avatarUri != null) {
|
||||||
|
customEditAvatarDialogBinding =
|
||||||
|
CustomEditAvatarDialogBinding.inflate(
|
||||||
|
LayoutInflater.from(context));
|
||||||
|
showUpdateAvatarDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private void openFileAttachment() {
|
||||||
|
|
||||||
|
String[] mimeTypes = {"image/webp", "image/gif", "image/jpg", "image/jpeg", "image/png"};
|
||||||
|
Intent data = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
|
data.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
|
data.setType("image/*");
|
||||||
|
data.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
|
||||||
|
Intent intent = Intent.createChooser(data, "Choose an image");
|
||||||
|
activityForAvatarUpdate.launch(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showUpdateAvatarDialog() {
|
||||||
|
|
||||||
|
View view = customEditAvatarDialogBinding.getRoot();
|
||||||
|
materialAlertDialogBuilder.setView(view);
|
||||||
|
|
||||||
|
PicassoService.getInstance(context)
|
||||||
|
.get()
|
||||||
|
.load(avatarUri)
|
||||||
|
.transform(new RoundedTransformation(imgRadius, 0))
|
||||||
|
.placeholder(R.drawable.loader_animated)
|
||||||
|
.resize(180, 180)
|
||||||
|
.centerCrop()
|
||||||
|
.into(customEditAvatarDialogBinding.userAvatar);
|
||||||
|
|
||||||
|
customEditAvatarDialogBinding.save.setOnClickListener(
|
||||||
|
saveUserAvatar -> saveUserAvatar(avatarUri));
|
||||||
|
|
||||||
|
dialogEditAvatar = materialAlertDialogBuilder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveUserAvatar(Uri avatar) {
|
||||||
|
|
||||||
|
InputStream imageStream = null;
|
||||||
|
try {
|
||||||
|
imageStream = context.getContentResolver().openInputStream(avatar);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.getMessage();
|
||||||
|
}
|
||||||
|
Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
|
||||||
|
|
||||||
|
String encodedString = AppUtil.imageEncodeToBase64(selectedImage);
|
||||||
|
|
||||||
|
UpdateUserAvatarOption updateUserAvatarOption = new UpdateUserAvatarOption();
|
||||||
|
updateUserAvatarOption.setImage(encodedString);
|
||||||
|
|
||||||
|
Call<Void> saveUserAvatar =
|
||||||
|
RetrofitClient.getApiInterface(context).userUpdateAvatar(updateUserAvatarOption);
|
||||||
|
|
||||||
|
saveUserAvatar.enqueue(
|
||||||
|
new Callback<>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(
|
||||||
|
@NonNull Call<Void> call, @NonNull retrofit2.Response<Void> response) {
|
||||||
|
|
||||||
|
if (response.code() == 204) {
|
||||||
|
|
||||||
|
dialogEditAvatar.dismiss();
|
||||||
|
getProfileDetail(username);
|
||||||
|
Toasty.success(context, getString(R.string.profileUpdate));
|
||||||
|
refProfile = true;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
Toasty.error(context, getString(R.string.genericError));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
|
||||||
|
|
||||||
|
Toasty.error(context, getString(R.string.genericServerResponseError));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void showEditProfileDialog() {
|
private void showEditProfileDialog() {
|
||||||
|
|
||||||
View view = customEditProfileBinding.getRoot();
|
View view = customEditProfileBinding.getRoot();
|
||||||
@ -160,7 +274,8 @@ public class DetailFragment extends Fragment {
|
|||||||
|
|
||||||
dialogEditSettings.dismiss();
|
dialogEditSettings.dismiss();
|
||||||
getProfileDetail(username);
|
getProfileDetail(username);
|
||||||
Toasty.success(context, getString(R.string.settingsSave));
|
Toasty.success(context, getString(R.string.profileUpdate));
|
||||||
|
refProfile = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Toasty.error(context, getString(R.string.genericError));
|
Toasty.error(context, getString(R.string.genericError));
|
||||||
@ -246,8 +361,6 @@ public class DetailFragment extends Fragment {
|
|||||||
? response.body().getEmail()
|
? response.body().getEmail()
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
int imgRadius = AppUtil.getPixelsFromDensity(context, 3);
|
|
||||||
|
|
||||||
binding.userFullName.setText(username);
|
binding.userFullName.setText(username);
|
||||||
binding.userLogin.setText(
|
binding.userLogin.setText(
|
||||||
getString(
|
getString(
|
||||||
|
@ -12,6 +12,7 @@ import android.content.pm.PackageManager;
|
|||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@ -24,6 +25,7 @@ import androidx.annotation.ColorInt;
|
|||||||
import androidx.browser.customtabs.CustomTabColorSchemeParams;
|
import androidx.browser.customtabs.CustomTabColorSchemeParams;
|
||||||
import androidx.browser.customtabs.CustomTabsIntent;
|
import androidx.browser.customtabs.CustomTabsIntent;
|
||||||
import androidx.core.content.pm.PackageInfoCompat;
|
import androidx.core.content.pm.PackageInfoCompat;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -413,6 +415,15 @@ public class AppUtil {
|
|||||||
return base64Str;
|
return base64Str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String imageEncodeToBase64(Bitmap image) {
|
||||||
|
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
image.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
|
||||||
|
byte[] bytes = byteArrayOutputStream.toByteArray();
|
||||||
|
|
||||||
|
return Base64.encodeToString(bytes, Base64.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
public static String decodeBase64(String str) {
|
public static String decodeBase64(String str) {
|
||||||
|
|
||||||
String base64Str = str;
|
String base64Str = str;
|
||||||
|
59
app/src/main/res/layout/custom_edit_avatar_dialog.xml
Normal file
59
app/src/main/res/layout/custom_edit_avatar_dialog.xml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?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:orientation="vertical"
|
||||||
|
android:padding="@dimen/dimen8dp">
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/mainView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="@dimen/dimen16dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="@dimen/dimen140dp"
|
||||||
|
android:layout_height="@dimen/dimen140dp"
|
||||||
|
style="?attr/materialCardViewFilledStyle"
|
||||||
|
android:layout_marginBottom="@dimen/dimen8dp"
|
||||||
|
app:cardElevation="@dimen/dimen0dp"
|
||||||
|
app:cardCornerRadius="@dimen/dimen48dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/userAvatar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:contentDescription="@string/generalImgContentText"
|
||||||
|
android:src="@mipmap/app_logo_round" />
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/save"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/dimen54dp"
|
||||||
|
android:layout_marginTop="@dimen/dimen16dp"
|
||||||
|
android:text="@string/saveButton"
|
||||||
|
android:textColor="?attr/materialCardBackgroundColor"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -91,17 +91,35 @@
|
|||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="@dimen/dimen14sp" />
|
android:textSize="@dimen/dimen14sp" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||||
android:id="@+id/editProfile"
|
android:id="@+id/metaProfile"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/editSettings"
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/update_avatar"
|
||||||
|
style="?attr/materialButtonToggleGroupStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:iconTint="?attr/materialCardBackgroundColor"
|
||||||
|
app:icon="@drawable/ic_person"
|
||||||
android:textColor="?attr/materialCardBackgroundColor"
|
android:textColor="?attr/materialCardBackgroundColor"
|
||||||
android:backgroundTint="?attr/fabColor"
|
android:textSize="@dimen/dimen14sp"
|
||||||
|
android:text="@string/userAvatar" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/update_profile"
|
||||||
|
style="?attr/materialButtonToggleGroupStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
app:iconTint="?attr/materialCardBackgroundColor"
|
app:iconTint="?attr/materialCardBackgroundColor"
|
||||||
app:icon="@drawable/ic_edit"
|
app:icon="@drawable/ic_edit"
|
||||||
android:textSize="14sp"
|
android:textColor="?attr/materialCardBackgroundColor"
|
||||||
android:visibility="gone" />
|
android:textSize="@dimen/dimen14sp"
|
||||||
|
android:text="@string/navProfile" />
|
||||||
|
|
||||||
|
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -360,6 +360,7 @@
|
|||||||
<string name="editSettings">Edit Profile</string>
|
<string name="editSettings">Edit Profile</string>
|
||||||
<string name="hideActivity">Hide Activity from profile page</string>
|
<string name="hideActivity">Hide Activity from profile page</string>
|
||||||
<string name="hideEmail">Hide Email</string>
|
<string name="hideEmail">Hide Email</string>
|
||||||
|
<string name="profileUpdate">Profile updated</string>
|
||||||
<!-- profile section -->
|
<!-- profile section -->
|
||||||
|
|
||||||
<!-- account settings -->
|
<!-- account settings -->
|
||||||
|
@ -1,25 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<changelog>
|
<changelog>
|
||||||
|
|
||||||
<release version="5.4.0" versioncode="540">
|
<release version="5.5.0-dev" versioncode="545">
|
||||||
<change>New: Restore/import app data</change>
|
<change>Under development</change>
|
||||||
<change>New: Backup/export app data</change>
|
|
||||||
<change>New: Delete email from account</change>
|
|
||||||
<change>New: Update profile settings</change>
|
|
||||||
<change>New: Add SSH key to account</change>
|
|
||||||
<change>Improvement: Open specific URL in deep links</change>
|
|
||||||
<change>Improvement: Show open in browser with other buttons in deep links</change>
|
|
||||||
<change>Improvement: Show pinned messages in timeline</change>
|
|
||||||
<change>Improvement: Hide Comment button if issue is locked</change>
|
|
||||||
<change>Improvement: New languages and translation updates</change>
|
|
||||||
<change>Bugfix: Fix crash on dynamic snackbar colors for older Android versions</change>
|
|
||||||
<change>Bugfix: Fix missing text after links in issue/pr</change>
|
|
||||||
<change>Bugfix: Fix emoji parsing in code blocks in issue/pr</change>
|
|
||||||
<change>Bugfix: Fix crash on null objects in timeline from API</change>
|
|
||||||
<change>Bugfix: Fix not seeing labels for repo admin when code option is disabled</change>
|
|
||||||
<change>Bugfix: Fix Task list in Markdown</change>
|
|
||||||
<change>Bugfix: Fix other issues related to Markdown</change>
|
|
||||||
<change>Bugfix: Fix crash on images with no path</change>
|
|
||||||
</release>
|
</release>
|
||||||
|
|
||||||
</changelog>
|
</changelog>
|
||||||
|
Loading…
Reference in New Issue
Block a user