mirror of
https://framagit.org/tom79/fedilab-tube
synced 2025-04-15 02:52:40 +02:00
Allow to edit profile + profile picture
This commit is contained in:
parent
fdc6e6e325
commit
0f38ad180a
@ -105,6 +105,7 @@ dependencies {
|
|||||||
implementation ("androidx.navigation:navigation-dynamic-features-fragment:2.3.1")
|
implementation ("androidx.navigation:navigation-dynamic-features-fragment:2.3.1")
|
||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||||
implementation 'androidx.browser:browser:1.2.0'
|
implementation 'androidx.browser:browser:1.2.0'
|
||||||
|
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||||
testImplementation 'junit:junit:4.13'
|
testImplementation 'junit:junit:4.13'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
<string name="set_autoplay_next_video_choice" translatable="false">set_autoplay_next_video_choice</string>
|
<string name="set_autoplay_next_video_choice" translatable="false">set_autoplay_next_video_choice</string>
|
||||||
<string name="set_store_in_history">set_store_in_history</string>
|
<string name="set_store_in_history">set_store_in_history</string>
|
||||||
|
|
||||||
|
<string name="change_profile_picture">Modifier la photo de profil</string>
|
||||||
|
<string name="account_updated">Le compte a été mis à jour !</string>
|
||||||
|
|
||||||
<string name="save">Enregistrer</string>
|
<string name="save">Enregistrer</string>
|
||||||
<string name="set_autoplay_next_video">Lire automatiquement la vidéo suivante</string>
|
<string name="set_autoplay_next_video">Lire automatiquement la vidéo suivante</string>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<string name="save">Save</string>
|
<string name="save">Save</string>
|
||||||
<string name="enable_history">Enable history</string>
|
<string name="enable_history">Enable history</string>
|
||||||
|
<string name="change_profile_picture">Change profile picture</string>
|
||||||
<string name="set_autoplay">Automatic playback</string>
|
<string name="set_autoplay">Automatic playback</string>
|
||||||
<string name="set_autoplay_description">If enabled, videos will be played automatically</string>
|
<string name="set_autoplay_description">If enabled, videos will be played automatically</string>
|
||||||
|
|
||||||
@ -87,6 +87,7 @@
|
|||||||
|
|
||||||
<string name="download_file">Download %1$s</string>
|
<string name="download_file">Download %1$s</string>
|
||||||
|
|
||||||
|
<string name="account_updated">The account has been updated!</string>
|
||||||
|
|
||||||
<string name="action_privacy">Privacy</string>
|
<string name="action_privacy">Privacy</string>
|
||||||
<string name="action_logout">Logout</string>
|
<string name="action_logout">Logout</string>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<application
|
<application
|
||||||
android:name=".FedilabTube"
|
android:name=".FedilabTube"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
|
android:requestLegacyExternalStorage="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
@ -1,17 +1,37 @@
|
|||||||
package app.fedilab.fedilabtube;
|
package app.fedilab.fedilabtube;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.documentfile.provider.DocumentFile;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
|
|
||||||
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
|
import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI;
|
||||||
import app.fedilab.fedilabtube.client.entities.Error;
|
import app.fedilab.fedilabtube.client.entities.Error;
|
||||||
|
import app.fedilab.fedilabtube.client.entities.UserMe;
|
||||||
import app.fedilab.fedilabtube.client.entities.UserSettings;
|
import app.fedilab.fedilabtube.client.entities.UserSettings;
|
||||||
import app.fedilab.fedilabtube.databinding.ActivityMyAccountSettingsBinding;
|
import app.fedilab.fedilabtube.databinding.ActivityMyAccountSettingsBinding;
|
||||||
|
import app.fedilab.fedilabtube.helper.Helper;
|
||||||
import es.dmoral.toasty.Toasty;
|
import es.dmoral.toasty.Toasty;
|
||||||
|
|
||||||
|
import static app.fedilab.fedilabtube.PeertubeUploadActivity.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE;
|
||||||
|
|
||||||
/* Copyright 2020 Thomas Schneider
|
/* Copyright 2020 Thomas Schneider
|
||||||
*
|
*
|
||||||
* This file is a part of TubeLab
|
* This file is a part of TubeLab
|
||||||
@ -30,6 +50,9 @@ import es.dmoral.toasty.Toasty;
|
|||||||
public class MyAccountActivity extends AppCompatActivity {
|
public class MyAccountActivity extends AppCompatActivity {
|
||||||
|
|
||||||
ActivityMyAccountSettingsBinding binding;
|
ActivityMyAccountSettingsBinding binding;
|
||||||
|
private static final int PICK_IMAGE = 466;
|
||||||
|
private Uri inputData;
|
||||||
|
private String fileName;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -48,19 +71,65 @@ public class MyAccountActivity extends AppCompatActivity {
|
|||||||
binding.displayname.setText(MainActivity.userMe.getAccount().getDisplayName());
|
binding.displayname.setText(MainActivity.userMe.getAccount().getDisplayName());
|
||||||
binding.description.setText(MainActivity.userMe.getAccount().getDescription());
|
binding.description.setText(MainActivity.userMe.getAccount().getDescription());
|
||||||
|
|
||||||
binding.save.setOnClickListener(v -> new Thread(() -> {
|
Helper.loadGiF(MyAccountActivity.this, MainActivity.userMe.getAccount().getAvatar()!=null?MainActivity.userMe.getAccount().getAvatar().getPath():null, binding.profilePicture);
|
||||||
UserSettings userSettings = new UserSettings();
|
|
||||||
userSettings.setDisplayName(binding.displayname.getText().toString().trim());
|
binding.selectFile.setOnClickListener(v->{
|
||||||
userSettings.setDescription(binding.description.getText().toString().trim());
|
if (ContextCompat.checkSelfPermission(MyAccountActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
|
||||||
try {
|
PackageManager.PERMISSION_GRANTED) {
|
||||||
RetrofitPeertubeAPI api = new RetrofitPeertubeAPI(MyAccountActivity.this);
|
ActivityCompat.requestPermissions(MyAccountActivity.this,
|
||||||
api.updateUser(userSettings);
|
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
|
||||||
MainActivity.userMe.getAccount().setDisplayName(binding.displayname.getText().toString().trim());
|
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
|
||||||
MainActivity.userMe.getAccount().setDescription(binding.description.getText().toString().trim());
|
return;
|
||||||
} catch (Exception | Error e) {
|
|
||||||
Toasty.error(MyAccountActivity.this, getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
|
|
||||||
}
|
}
|
||||||
}).start());
|
|
||||||
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
|
intent.setType("*/*");
|
||||||
|
String[] mimetypes = {"image/*"};
|
||||||
|
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
|
||||||
|
startActivityForResult(intent, PICK_IMAGE);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
binding.save.setOnClickListener(v -> {
|
||||||
|
binding.save.setEnabled(false);
|
||||||
|
new Thread(() -> {
|
||||||
|
UserSettings userSettings = new UserSettings();
|
||||||
|
if( binding.displayname.getText() != null) {
|
||||||
|
userSettings.setDisplayName(binding.displayname.getText().toString().trim());
|
||||||
|
}
|
||||||
|
if( binding.description.getText() != null) {
|
||||||
|
userSettings.setDescription(binding.description.getText().toString().trim());
|
||||||
|
}
|
||||||
|
if( inputData != null ) {
|
||||||
|
userSettings.setAvatarfile(inputData);
|
||||||
|
userSettings.setFileName(fileName);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
RetrofitPeertubeAPI api = new RetrofitPeertubeAPI(MyAccountActivity.this);
|
||||||
|
UserMe.AvatarResponse avatarResponse = api.updateUser(userSettings);
|
||||||
|
MainActivity.userMe.getAccount().setDisplayName(binding.displayname.getText().toString().trim());
|
||||||
|
MainActivity.userMe.getAccount().setDescription(binding.description.getText().toString().trim());
|
||||||
|
if( avatarResponse != null && avatarResponse.getAvatar() != null ) {
|
||||||
|
MainActivity.userMe.getAccount().setAvatar(avatarResponse.getAvatar());
|
||||||
|
}
|
||||||
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
Runnable myRunnable = () -> {
|
||||||
|
Toasty.info(MyAccountActivity.this, getString(R.string.account_updated), Toasty.LENGTH_LONG).show();
|
||||||
|
binding.save.setEnabled(true);
|
||||||
|
};
|
||||||
|
mainHandler.post(myRunnable);
|
||||||
|
} catch (Exception | Error e) {
|
||||||
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
Runnable myRunnable = () -> {
|
||||||
|
Toasty.error(MyAccountActivity.this, getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
|
||||||
|
binding.save.setEnabled(true);
|
||||||
|
};
|
||||||
|
mainHandler.post(myRunnable);
|
||||||
|
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -71,4 +140,27 @@ public class MyAccountActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {
|
||||||
|
if (data == null || data.getData() == null) {
|
||||||
|
Toasty.error(MyAccountActivity.this, getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inputData = data.getData();
|
||||||
|
DocumentFile documentFile = DocumentFile.fromSingleUri(this, inputData);
|
||||||
|
if (documentFile != null) {
|
||||||
|
fileName = documentFile.getName();
|
||||||
|
}
|
||||||
|
Glide.with(MyAccountActivity.this)
|
||||||
|
.load(inputData)
|
||||||
|
.thumbnail(0.1f)
|
||||||
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
||||||
|
.into(binding.profilePicture);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ public class PeertubeUploadActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
|
|
||||||
private final int PICK_IVDEO = 52378;
|
private final int PICK_IVDEO = 52378;
|
||||||
private final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 724;
|
public static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 724;
|
||||||
private Button set_upload_file, set_upload_submit;
|
private Button set_upload_file, set_upload_submit;
|
||||||
private Spinner set_upload_privacy, set_upload_channel;
|
private Spinner set_upload_privacy, set_upload_channel;
|
||||||
private TextView set_upload_file_name;
|
private TextView set_upload_file_name;
|
||||||
|
@ -138,7 +138,7 @@ public interface PeertubeService {
|
|||||||
|
|
||||||
@Multipart
|
@Multipart
|
||||||
@POST("users/me/avatar/pick")
|
@POST("users/me/avatar/pick")
|
||||||
Call<String> updateProfilePicture(
|
Call<UserMe.AvatarResponse> updateProfilePicture(
|
||||||
@Header("Authorization") String credentials,
|
@Header("Authorization") String credentials,
|
||||||
@Part MultipartBody.Part avatarfile);
|
@Part MultipartBody.Part avatarfile);
|
||||||
|
|
||||||
|
@ -21,9 +21,12 @@ import android.content.SharedPreferences;
|
|||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.webkit.MimeTypeMap;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
@ -451,8 +454,9 @@ public class RetrofitPeertubeAPI {
|
|||||||
*
|
*
|
||||||
* @param userSettings UserSettings
|
* @param userSettings UserSettings
|
||||||
*/
|
*/
|
||||||
public void updateUser(UserSettings userSettings) throws IOException, Error {
|
public UserMe.AvatarResponse updateUser(UserSettings userSettings) throws IOException, Error {
|
||||||
APIResponse apiResponse = new APIResponse();
|
APIResponse apiResponse = new APIResponse();
|
||||||
|
UserMe.AvatarResponse avatarResponse = null;
|
||||||
PeertubeService peertubeService = init();
|
PeertubeService peertubeService = init();
|
||||||
Call<String> updateUser = peertubeService.updateUser(getToken(),
|
Call<String> updateUser = peertubeService.updateUser(getToken(),
|
||||||
userSettings.isVideosHistoryEnabled(),
|
userSettings.isVideosHistoryEnabled(),
|
||||||
@ -473,15 +477,45 @@ public class RetrofitPeertubeAPI {
|
|||||||
if (response.errorBody() != null) {
|
if (response.errorBody() != null) {
|
||||||
error.setError(response.errorBody().string());
|
error.setError(response.errorBody().string());
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
error.setError(_context.getString(R.string.toast_error));
|
error.setError(_context.getString(R.string.toast_error));
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
if (userSettings.getAvatarfile() != null) {
|
if (userSettings.getAvatarfile() != null) {
|
||||||
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), userSettings.getAvatarfile());
|
InputStream inputStream = _context.getContentResolver().openInputStream(userSettings.getAvatarfile());
|
||||||
MultipartBody.Part bodyThumbnail = MultipartBody.Part.createFormData("avatarfile", userSettings.getAvatarfile().getName(), requestFile);
|
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
|
||||||
Call<String> updateProfilePicture = peertubeService.updateProfilePicture(getToken(), bodyThumbnail);
|
int bufferSize = 1024;
|
||||||
|
byte[] buffer = new byte[bufferSize];
|
||||||
|
|
||||||
|
int len;
|
||||||
|
while ((len = inputStream.read(buffer)) != -1) {
|
||||||
|
byteBuffer.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
byte[] imageBytes = byteBuffer.toByteArray();
|
||||||
|
String mime = MimeTypeMap.getFileExtensionFromUrl(userSettings.getAvatarfile().toString());
|
||||||
|
if( mime == null || mime.trim().length() == 0) {
|
||||||
|
mime = "png";
|
||||||
|
}
|
||||||
|
RequestBody requestFile = RequestBody.create(MediaType.parse("image/"+mime), imageBytes);
|
||||||
|
MultipartBody.Part bodyThumbnail = MultipartBody.Part.createFormData("avatarfile", userSettings.getFileName(), requestFile);
|
||||||
|
Call<UserMe.AvatarResponse> updateProfilePicture = peertubeService.updateProfilePicture(getToken(), bodyThumbnail);
|
||||||
|
Response<UserMe.AvatarResponse> responseAvatar = updateProfilePicture.execute();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
avatarResponse = responseAvatar.body();
|
||||||
|
} else {
|
||||||
|
setError(apiResponse, response.code(), response.errorBody());
|
||||||
|
Error error = new Error();
|
||||||
|
error.setStatusCode(response.code());
|
||||||
|
if (response.errorBody() != null) {
|
||||||
|
error.setError(response.errorBody().string());
|
||||||
|
} else {
|
||||||
|
error.setError(_context.getString(R.string.toast_error));
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return avatarResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -265,4 +265,18 @@ public class UserMe {
|
|||||||
public void setAutoPlayVideo(boolean autoPlayVideo) {
|
public void setAutoPlayVideo(boolean autoPlayVideo) {
|
||||||
this.autoPlayVideo = autoPlayVideo;
|
this.autoPlayVideo = autoPlayVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class AvatarResponse {
|
||||||
|
@SerializedName("avatar")
|
||||||
|
private Avatar avatar;
|
||||||
|
|
||||||
|
public Avatar getAvatar() {
|
||||||
|
return avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatar(Avatar avatar) {
|
||||||
|
this.avatar = avatar;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,9 @@ package app.fedilab.fedilabtube.client.entities;
|
|||||||
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
|
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||||
public class UserSettings {
|
public class UserSettings {
|
||||||
@ -27,7 +28,8 @@ public class UserSettings {
|
|||||||
private List<String> videoLanguages;
|
private List<String> videoLanguages;
|
||||||
private String description;
|
private String description;
|
||||||
private String displayName;
|
private String displayName;
|
||||||
private File avatarfile;
|
private Uri avatarfile;
|
||||||
|
private String fileName;
|
||||||
|
|
||||||
public Boolean isVideosHistoryEnabled() {
|
public Boolean isVideosHistoryEnabled() {
|
||||||
return videosHistoryEnabled;
|
return videosHistoryEnabled;
|
||||||
@ -77,11 +79,11 @@ public class UserSettings {
|
|||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getAvatarfile() {
|
public Uri getAvatarfile() {
|
||||||
return avatarfile;
|
return avatarfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAvatarfile(File avatarfile) {
|
public void setAvatarfile(Uri avatarfile) {
|
||||||
this.avatarfile = avatarfile;
|
this.avatarfile = avatarfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,4 +106,21 @@ public class UserSettings {
|
|||||||
public void setAutoPlayNextVideo(Boolean autoPlayNextVideo) {
|
public void setAutoPlayNextVideo(Boolean autoPlayNextVideo) {
|
||||||
this.autoPlayNextVideo = autoPlayNextVideo;
|
this.autoPlayNextVideo = autoPlayNextVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getAutoPlayNextVideo() {
|
||||||
|
return autoPlayNextVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileName(String fileName) {
|
||||||
|
if( fileName == null) {
|
||||||
|
this.fileName = "avatar.png";
|
||||||
|
} else {
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,17 +5,34 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
>
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_marginTop="50dp"
|
||||||
|
android:id="@+id/profile_picture"
|
||||||
|
android:layout_marginStart="50dp"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:contentDescription="@string/profile_picture"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"/>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/select_file"
|
||||||
|
style="@style/Widget.AppCompat.Button.Borderless"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/change_profile_picture"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/profile_picture"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/profile_picture" />
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/displayname_container"
|
android:id="@+id/displayname_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_marginTop="50dp"
|
android:layout_marginTop="30dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="50dp"
|
android:layout_marginStart="50dp"
|
||||||
android:layout_marginEnd="50dp"
|
android:layout_marginEnd="50dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toBottomOf="@+id/profile_picture">
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/displayname"
|
android:id="@+id/displayname"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user