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.lifecycle:lifecycle-extensions:2.2.0'
|
||||
implementation 'androidx.browser:browser:1.2.0'
|
||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||
testImplementation 'junit:junit:4.13'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
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_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="set_autoplay_next_video">Lire automatiquement la vidéo suivante</string>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
<string name="save">Save</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_description">If enabled, videos will be played automatically</string>
|
||||
|
||||
|
@ -87,6 +87,7 @@
|
|||
|
||||
<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_logout">Logout</string>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<application
|
||||
android:name=".FedilabTube"
|
||||
android:allowBackup="false"
|
||||
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
|
|
|
@ -1,17 +1,37 @@
|
|||
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.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
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.entities.Error;
|
||||
import app.fedilab.fedilabtube.client.entities.UserMe;
|
||||
import app.fedilab.fedilabtube.client.entities.UserSettings;
|
||||
import app.fedilab.fedilabtube.databinding.ActivityMyAccountSettingsBinding;
|
||||
import app.fedilab.fedilabtube.helper.Helper;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
|
||||
import static app.fedilab.fedilabtube.PeertubeUploadActivity.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE;
|
||||
|
||||
/* Copyright 2020 Thomas Schneider
|
||||
*
|
||||
* This file is a part of TubeLab
|
||||
|
@ -30,6 +50,9 @@ import es.dmoral.toasty.Toasty;
|
|||
public class MyAccountActivity extends AppCompatActivity {
|
||||
|
||||
ActivityMyAccountSettingsBinding binding;
|
||||
private static final int PICK_IMAGE = 466;
|
||||
private Uri inputData;
|
||||
private String fileName;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -48,19 +71,65 @@ public class MyAccountActivity extends AppCompatActivity {
|
|||
binding.displayname.setText(MainActivity.userMe.getAccount().getDisplayName());
|
||||
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);
|
||||
|
||||
binding.selectFile.setOnClickListener(v->{
|
||||
if (ContextCompat.checkSelfPermission(MyAccountActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(MyAccountActivity.this,
|
||||
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
|
||||
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
api.updateUser(userSettings);
|
||||
UserMe.AvatarResponse avatarResponse = api.updateUser(userSettings);
|
||||
MainActivity.userMe.getAccount().setDisplayName(binding.displayname.getText().toString().trim());
|
||||
MainActivity.userMe.getAccount().setDescription(binding.description.getText().toString().trim());
|
||||
} catch (Exception | Error e) {
|
||||
Toasty.error(MyAccountActivity.this, getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
|
||||
if( avatarResponse != null && avatarResponse.getAvatar() != null ) {
|
||||
MainActivity.userMe.getAccount().setAvatar(avatarResponse.getAvatar());
|
||||
}
|
||||
}).start());
|
||||
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
|
||||
|
@ -71,4 +140,27 @@ public class MyAccountActivity extends AppCompatActivity {
|
|||
}
|
||||
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 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 Spinner set_upload_privacy, set_upload_channel;
|
||||
private TextView set_upload_file_name;
|
||||
|
|
|
@ -138,7 +138,7 @@ public interface PeertubeService {
|
|||
|
||||
@Multipart
|
||||
@POST("users/me/avatar/pick")
|
||||
Call<String> updateProfilePicture(
|
||||
Call<UserMe.AvatarResponse> updateProfilePicture(
|
||||
@Header("Authorization") String credentials,
|
||||
@Part MultipartBody.Part avatarfile);
|
||||
|
||||
|
|
|
@ -21,9 +21,12 @@ import android.content.SharedPreferences;
|
|||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
|
@ -451,8 +454,9 @@ public class RetrofitPeertubeAPI {
|
|||
*
|
||||
* @param userSettings UserSettings
|
||||
*/
|
||||
public void updateUser(UserSettings userSettings) throws IOException, Error {
|
||||
public UserMe.AvatarResponse updateUser(UserSettings userSettings) throws IOException, Error {
|
||||
APIResponse apiResponse = new APIResponse();
|
||||
UserMe.AvatarResponse avatarResponse = null;
|
||||
PeertubeService peertubeService = init();
|
||||
Call<String> updateUser = peertubeService.updateUser(getToken(),
|
||||
userSettings.isVideosHistoryEnabled(),
|
||||
|
@ -473,15 +477,45 @@ public class RetrofitPeertubeAPI {
|
|||
if (response.errorBody() != null) {
|
||||
error.setError(response.errorBody().string());
|
||||
} else {
|
||||
|
||||
error.setError(_context.getString(R.string.toast_error));
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
if (userSettings.getAvatarfile() != null) {
|
||||
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), userSettings.getAvatarfile());
|
||||
MultipartBody.Part bodyThumbnail = MultipartBody.Part.createFormData("avatarfile", userSettings.getAvatarfile().getName(), requestFile);
|
||||
Call<String> updateProfilePicture = peertubeService.updateProfilePicture(getToken(), bodyThumbnail);
|
||||
InputStream inputStream = _context.getContentResolver().openInputStream(userSettings.getAvatarfile());
|
||||
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
|
||||
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) {
|
||||
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,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import java.util.List;
|
||||
import java.io.File;
|
||||
|
||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||
public class UserSettings {
|
||||
|
@ -27,7 +28,8 @@ public class UserSettings {
|
|||
private List<String> videoLanguages;
|
||||
private String description;
|
||||
private String displayName;
|
||||
private File avatarfile;
|
||||
private Uri avatarfile;
|
||||
private String fileName;
|
||||
|
||||
public Boolean isVideosHistoryEnabled() {
|
||||
return videosHistoryEnabled;
|
||||
|
@ -77,11 +79,11 @@ public class UserSettings {
|
|||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public File getAvatarfile() {
|
||||
public Uri getAvatarfile() {
|
||||
return avatarfile;
|
||||
}
|
||||
|
||||
public void setAvatarfile(File avatarfile) {
|
||||
public void setAvatarfile(Uri avatarfile) {
|
||||
this.avatarfile = avatarfile;
|
||||
}
|
||||
|
||||
|
@ -104,4 +106,21 @@ public class UserSettings {
|
|||
public void setAutoPlayNextVideo(Boolean 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_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
|
||||
android:id="@+id/displayname_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="50dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="50dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
app:layout_constraintTop_toBottomOf="@+id/profile_picture">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/displayname"
|
||||
android:layout_width="match_parent"
|
||||
|
|
Loading…
Reference in New Issue