mirror of https://codeberg.org/gitnex/GitNex.git
Upload files when creating an issue..
This commit is contained in:
parent
431583841d
commit
525d8bba99
|
@ -1,17 +1,28 @@
|
|||
package org.mian.gitnex.activities;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
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.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||
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;
|
||||
|
@ -21,6 +32,9 @@ 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;
|
||||
|
@ -30,9 +44,11 @@ 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;
|
||||
|
@ -40,7 +56,10 @@ import org.mian.gitnex.helpers.AlertDialogs;
|
|||
import org.mian.gitnex.helpers.Constants;
|
||||
import org.mian.gitnex.helpers.Markdown;
|
||||
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 org.mian.gitnex.structs.BottomSheetListener;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
|
||||
|
@ -49,7 +68,9 @@ import retrofit2.Callback;
|
|||
*/
|
||||
public class CreateIssueActivity extends BaseActivity
|
||||
implements LabelsListAdapter.LabelsListAdapterListener,
|
||||
AssigneesListAdapter.AssigneesListAdapterListener {
|
||||
AssigneesListAdapter.AssigneesListAdapterListener,
|
||||
BottomSheetListener,
|
||||
AttachmentsAdapter.AttachmentsReceiverListener {
|
||||
|
||||
private final List<Label> labelsList = new ArrayList<>();
|
||||
private final LinkedHashMap<String, Milestone> milestonesList = new LinkedHashMap<>();
|
||||
|
@ -64,6 +85,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
|
||||
|
@ -83,6 +107,11 @@ public class CreateIssueActivity extends BaseActivity
|
|||
|
||||
int resultLimit = Constants.getCurrentResultLimit(ctx);
|
||||
|
||||
attachmentsList = new ArrayList<>();
|
||||
attachmentsAdapter = new AttachmentsAdapter(attachmentsList, ctx);
|
||||
|
||||
AttachmentsAdapter.setAttachmentsReceiveListener(this);
|
||||
|
||||
viewBinding.newIssueDescription.setOnTouchListener(
|
||||
(touchView, motionEvent) -> {
|
||||
touchView.getParent().requestDisallowInterceptTouchEvent(true);
|
||||
|
@ -103,11 +132,13 @@ public class CreateIssueActivity extends BaseActivity
|
|||
showDatePickerDialog();
|
||||
|
||||
viewBinding.newIssueDueDateLayout.setEndIconOnClickListener(
|
||||
view -> {
|
||||
viewBinding.newIssueDueDate.setText("");
|
||||
});
|
||||
view -> viewBinding.newIssueDueDate.setText(""));
|
||||
|
||||
viewBinding.topAppBar.setNavigationOnClickListener(v -> finish());
|
||||
viewBinding.topAppBar.setNavigationOnClickListener(
|
||||
v -> {
|
||||
finish();
|
||||
contentUri.clear();
|
||||
});
|
||||
|
||||
viewBinding.topAppBar.setOnMenuItemClickListener(
|
||||
menuItem -> {
|
||||
|
@ -139,6 +170,9 @@ public class CreateIssueActivity extends BaseActivity
|
|||
} else if (id == R.id.create) {
|
||||
processNewIssue();
|
||||
return true;
|
||||
} else if (id == R.id.attachment) {
|
||||
checkForAttachments();
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(menuItem);
|
||||
}
|
||||
|
@ -159,6 +193,154 @@ public class CreateIssueActivity extends BaseActivity
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
public void onDestroy() {
|
||||
AttachmentsAdapter.setAttachmentsReceiveListener(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttachmentsData(Uri filename) {
|
||||
contentUri.remove(filename);
|
||||
}
|
||||
|
||||
public class BottomSheetAttachments extends BottomSheetDialogFragment {
|
||||
|
||||
private BottomSheetListener bmListener;
|
||||
|
||||
@Nullable @Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
BottomSheetAttachmentsBinding bottomSheetAttachmentsBinding =
|
||||
BottomSheetAttachmentsBinding.inflate(inflater, container, false);
|
||||
|
||||
bottomSheetAttachmentsBinding.addAttachment.setOnClickListener(
|
||||
v1 -> bmListener.onButtonClicked("addAttachment"));
|
||||
|
||||
bottomSheetAttachmentsBinding.recyclerViewAttachments.setHasFixedSize(true);
|
||||
bottomSheetAttachmentsBinding.recyclerViewAttachments.setLayoutManager(
|
||||
new LinearLayoutManager(getContext()));
|
||||
bottomSheetAttachmentsBinding.recyclerViewAttachments.setAdapter(attachmentsAdapter);
|
||||
|
||||
return bottomSheetAttachmentsBinding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
|
||||
super.onAttach(context);
|
||||
|
||||
try {
|
||||
bmListener = (BottomSheetListener) context;
|
||||
} catch (ClassCastException e) {
|
||||
throw new ClassCastException(context + " must implement BottomSheetListener");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onButtonClicked(String text) {
|
||||
|
||||
if ("addAttachment".equals(text)) {
|
||||
openFileAttachmentActivity();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForAttachments() {
|
||||
|
||||
if (contentUri.size() > 0) {
|
||||
BottomSheetAttachments bottomSheet = new BottomSheetAttachments();
|
||||
bottomSheet.show(getSupportFragmentManager(), "attachmentsBottomSheet");
|
||||
} else {
|
||||
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 < attachmentsAdapter.getItemCount(); 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 showDatePickerDialog() {
|
||||
|
||||
MaterialDatePicker.Builder<Long> builder = MaterialDatePicker.Builder.datePicker();
|
||||
|
@ -324,7 +506,14 @@ public class CreateIssueActivity extends BaseActivity
|
|||
findViewById(android.R.id.content),
|
||||
getString(R.string.issueCreated));
|
||||
|
||||
new Handler().postDelayed(() -> finish(), 3000);
|
||||
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) {
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -15,7 +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_neutral0));
|
||||
snackBar.setBackgroundTint(context.getColor(R.color.material_dynamic_neutral10));
|
||||
textView.setTextColor(context.getColor(R.color.colorWhite));
|
||||
snackBar.show();
|
||||
}
|
||||
|
@ -24,7 +24,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_neutral0));
|
||||
snackBar.setBackgroundTint(context.getColor(R.color.material_dynamic_neutral10));
|
||||
textView.setTextColor(context.getColor(R.color.colorWhite));
|
||||
snackBar.show();
|
||||
}
|
||||
|
@ -33,8 +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);
|
||||
snackBar.setBackgroundTint(context.getColor(R.color.material_dynamic_neutral0));
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,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);
|
||||
snackBar.setBackgroundTint(context.getColor(R.color.material_dynamic_neutral0));
|
||||
textView.setTextColor(context.getColor(R.color.materialcolorpicker__red));
|
||||
snackBar.setBackgroundTint(context.getColor(R.color.material_dynamic_neutral10));
|
||||
textView.setTextColor(context.getColor(R.color.darkRed));
|
||||
snackBar.show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -27,7 +27,7 @@
|
|||
android:layout_height="?attr/actionBarSize"
|
||||
app:title="@string/pageTitleCreateNewIssue"
|
||||
app:layout_collapseMode="pin"
|
||||
app:menu="@menu/create_menu"
|
||||
app:menu="@menu/create_issue_menu"
|
||||
app:navigationIcon="@drawable/ic_close" />
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
@ -3,17 +3,24 @@
|
|||
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="0"
|
||||
android:orderInCategory="1"
|
||||
android:title="@string/strMarkdown"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/create"
|
||||
android:title="@string/newCreateButtonCopy"
|
||||
android:orderInCategory="1"
|
||||
android:orderInCategory="2"
|
||||
android:contentDescription="@string/newCreateButtonCopy"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
|
@ -875,4 +875,8 @@
|
|||
<string name="lang_percentage" translatable="false">%s%%</string>
|
||||
|
||||
<string name="dashboard">Dashboard</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>
|
||||
|
|
Loading…
Reference in New Issue