Merge pull request #8005 from nextcloud/template
Template Dialog: template needs to be selected
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9 KiB |
|
@ -1,2 +1,2 @@
|
|||
DO NOT TOUCH; GENERATED BY DRONE
|
||||
<span class="mdl-layout-title">Lint Report: 240 warnings</span>
|
||||
<span class="mdl-layout-title">Lint Report: 232 warnings</span>
|
||||
|
|
|
@ -278,7 +278,7 @@ public class DialogFragmentIT extends AbstractIT {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void showTemplate(Creator creator) {
|
||||
public void showTemplate(Creator creator, String headline) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ public class PassCodeActivity extends AppCompatActivity implements Injectable {
|
|||
|
||||
int elementColor = ThemeUtils.primaryColor(this, true);
|
||||
|
||||
ThemeUtils.themeDialogActionButton(binding.cancel);
|
||||
ThemeUtils.themeBorderlessButton(binding.cancel, ThemeUtils.primaryColor(this, true));
|
||||
|
||||
passCodeEditTexts[0] = binding.txt0;
|
||||
ThemeUtils.colorEditText(passCodeEditTexts[0], elementColor);
|
||||
|
|
|
@ -26,16 +26,16 @@ import android.content.Context;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.nextcloud.client.account.CurrentAccountProvider;
|
||||
import com.nextcloud.client.network.ClientFactory;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.databinding.TemplateButtonBinding;
|
||||
import com.owncloud.android.datamodel.Template;
|
||||
import com.owncloud.android.ui.dialog.ChooseRichDocumentsTemplateDialogFragment;
|
||||
import com.owncloud.android.utils.NextcloudServer;
|
||||
import com.owncloud.android.utils.ThemeUtils;
|
||||
import com.owncloud.android.utils.glide.CustomGlideStreamLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -43,8 +43,6 @@ import java.util.List;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
/**
|
||||
* Adapter for handling Templates, used to create files out of it via RichDocuments app
|
||||
|
@ -57,6 +55,9 @@ public class RichDocumentsTemplateAdapter extends RecyclerView.Adapter<RichDocum
|
|||
private ChooseRichDocumentsTemplateDialogFragment.Type type;
|
||||
private CurrentAccountProvider currentAccountProvider;
|
||||
private ClientFactory clientFactory;
|
||||
private Template selectedTemplate;
|
||||
private final int colorSelected;
|
||||
private final int colorUnselected;
|
||||
|
||||
public RichDocumentsTemplateAdapter(
|
||||
ChooseRichDocumentsTemplateDialogFragment.Type type,
|
||||
|
@ -70,13 +71,19 @@ public class RichDocumentsTemplateAdapter extends RecyclerView.Adapter<RichDocum
|
|||
this.context = context;
|
||||
this.currentAccountProvider = currentAccountProvider;
|
||||
this.clientFactory = clientFactory;
|
||||
colorSelected = ThemeUtils.primaryColor(context, true);
|
||||
colorUnselected = context.getResources().getColor(R.color.grey_200);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
@NextcloudServer(max = 18) // remove entire class
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.template_button, parent, false));
|
||||
return new RichDocumentsTemplateAdapter.ViewHolder(
|
||||
TemplateButtonBinding.inflate(LayoutInflater.from(parent.getContext()),
|
||||
parent,
|
||||
false)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,6 +95,15 @@ public class RichDocumentsTemplateAdapter extends RecyclerView.Adapter<RichDocum
|
|||
this.templateList = templateList;
|
||||
}
|
||||
|
||||
public void setTemplateAsActive(Template template) {
|
||||
selectedTemplate = template;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public Template getSelectedTemplate() {
|
||||
return selectedTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return templateList.size();
|
||||
|
@ -95,17 +111,12 @@ public class RichDocumentsTemplateAdapter extends RecyclerView.Adapter<RichDocum
|
|||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
|
||||
@BindView(R.id.name)
|
||||
public TextView name;
|
||||
|
||||
@BindView(R.id.thumbnail)
|
||||
public ImageView thumbnail;
|
||||
|
||||
private final TemplateButtonBinding binding;
|
||||
private Template template;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
public ViewHolder(@NonNull TemplateButtonBinding binding) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
itemView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
|
@ -143,9 +154,15 @@ public class RichDocumentsTemplateAdapter extends RecyclerView.Adapter<RichDocum
|
|||
load(template.getThumbnailLink())
|
||||
.placeholder(placeholder)
|
||||
.error(placeholder)
|
||||
.into(thumbnail);
|
||||
.into(binding.template);
|
||||
|
||||
name.setText(template.getName());
|
||||
binding.templateName.setText(template.getName());
|
||||
|
||||
if (template == selectedTemplate) {
|
||||
binding.templateContainer.setStrokeColor(colorSelected);
|
||||
} else {
|
||||
binding.templateContainer.setStrokeColor(colorUnselected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,22 +29,20 @@ import android.graphics.drawable.Drawable;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.nextcloud.client.account.CurrentAccountProvider;
|
||||
import com.nextcloud.client.network.ClientFactory;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.databinding.TemplateButtonBinding;
|
||||
import com.owncloud.android.lib.common.Template;
|
||||
import com.owncloud.android.lib.common.TemplateList;
|
||||
import com.owncloud.android.utils.MimeTypeUtil;
|
||||
import com.owncloud.android.utils.ThemeUtils;
|
||||
import com.owncloud.android.utils.glide.CustomGlideStreamLoader;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
/**
|
||||
* Adapter for handling Templates, used to create files out of it via RichDocuments app
|
||||
|
@ -57,6 +55,9 @@ public class TemplateAdapter extends RecyclerView.Adapter<TemplateAdapter.ViewHo
|
|||
private CurrentAccountProvider currentAccountProvider;
|
||||
private ClientFactory clientFactory;
|
||||
private String mimetype;
|
||||
private Template selectedTemplate;
|
||||
private final int colorSelected;
|
||||
private final int colorUnselected;
|
||||
|
||||
public TemplateAdapter(
|
||||
String mimetype,
|
||||
|
@ -70,12 +71,18 @@ public class TemplateAdapter extends RecyclerView.Adapter<TemplateAdapter.ViewHo
|
|||
this.context = context;
|
||||
this.currentAccountProvider = currentAccountProvider;
|
||||
this.clientFactory = clientFactory;
|
||||
colorSelected = ThemeUtils.primaryColor(context, true);
|
||||
colorUnselected = context.getResources().getColor(R.color.grey_200);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.template_button, parent, false));
|
||||
return new TemplateAdapter.ViewHolder(
|
||||
TemplateButtonBinding.inflate(LayoutInflater.from(parent.getContext()),
|
||||
parent,
|
||||
false)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,23 +94,28 @@ public class TemplateAdapter extends RecyclerView.Adapter<TemplateAdapter.ViewHo
|
|||
this.templateList = templateList;
|
||||
}
|
||||
|
||||
public void setTemplateAsActive(Template template) {
|
||||
selectedTemplate = template;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public Template getSelectedTemplate() {
|
||||
return selectedTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return templateList.getTemplateList().size();
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
@BindView(R.id.name)
|
||||
public TextView name;
|
||||
|
||||
@BindView(R.id.thumbnail)
|
||||
public ImageView thumbnail;
|
||||
|
||||
private final TemplateButtonBinding binding;
|
||||
private Template template;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
public ViewHolder(@NonNull TemplateButtonBinding binding) {
|
||||
super(binding.getRoot());
|
||||
this.binding = binding;
|
||||
itemView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
|
@ -124,11 +136,17 @@ public class TemplateAdapter extends RecyclerView.Adapter<TemplateAdapter.ViewHo
|
|||
|
||||
Glide.with(context).using(new CustomGlideStreamLoader(currentAccountProvider, clientFactory))
|
||||
.load(template.getPreview())
|
||||
.placeholder(placeholder)
|
||||
.error(placeholder)
|
||||
.into(thumbnail);
|
||||
.placeholder(placeholder)
|
||||
.error(placeholder)
|
||||
.into(binding.template);
|
||||
|
||||
name.setText(template.getTitle());
|
||||
binding.templateName.setText(template.getTitle());
|
||||
|
||||
if (template == selectedTemplate) {
|
||||
binding.templateContainer.setStrokeColor(colorSelected);
|
||||
} else {
|
||||
binding.templateContainer.setStrokeColor(colorUnselected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,19 +22,16 @@
|
|||
|
||||
package com.owncloud.android.ui.dialog;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.nextcloud.client.account.CurrentAccountProvider;
|
||||
import com.nextcloud.client.account.User;
|
||||
|
@ -42,6 +39,7 @@ import com.nextcloud.client.di.Injectable;
|
|||
import com.nextcloud.client.network.ClientFactory;
|
||||
import com.owncloud.android.MainApp;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.databinding.ChooseTemplateBinding;
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.datamodel.Template;
|
||||
|
@ -72,26 +70,25 @@ import androidx.annotation.NonNull;
|
|||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
/**
|
||||
* Dialog to show templates for new documents/spreadsheets/presentations.
|
||||
*/
|
||||
public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment implements DialogInterface.OnClickListener,
|
||||
public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment implements View.OnClickListener,
|
||||
RichDocumentsTemplateAdapter.ClickListener, Injectable {
|
||||
|
||||
private static final String ARG_PARENT_FOLDER = "PARENT_FOLDER";
|
||||
private static final String ARG_TYPE = "TYPE";
|
||||
private static final String TAG = ChooseRichDocumentsTemplateDialogFragment.class.getSimpleName();
|
||||
private static final String DOT = ".";
|
||||
public static final int SINGLE_TEMPLATE = 1;
|
||||
|
||||
private RichDocumentsTemplateAdapter adapter;
|
||||
private OCFile parentFolder;
|
||||
private OwnCloudClient client;
|
||||
@Inject CurrentAccountProvider currentAccount;
|
||||
@Inject ClientFactory clientFactory;
|
||||
private Button positiveButton;
|
||||
|
||||
public enum Type {
|
||||
DOCUMENT,
|
||||
|
@ -99,11 +96,7 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
PRESENTATION
|
||||
}
|
||||
|
||||
@BindView(R.id.list)
|
||||
RecyclerView listView;
|
||||
|
||||
@BindView(R.id.filename)
|
||||
EditText fileName;
|
||||
ChooseTemplateBinding binding;
|
||||
|
||||
@NextcloudServer(max = 18) // will be removed in favor of generic direct editing
|
||||
public static ChooseRichDocumentsTemplateDialogFragment newInstance(OCFile parentFolder, Type type) {
|
||||
|
@ -113,7 +106,6 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
args.putString(ARG_TYPE, type.name());
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,8 +116,14 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
|
||||
AlertDialog alertDialog = (AlertDialog) getDialog();
|
||||
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(color);
|
||||
alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(color);
|
||||
positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
ThemeUtils.themeBorderlessButton(positiveButton, color);
|
||||
positiveButton.setOnClickListener(this);
|
||||
positiveButton.setEnabled(false);
|
||||
|
||||
ThemeUtils.themeBorderlessButton(alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL), color);
|
||||
|
||||
checkEnablingCreateButton();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -141,37 +139,36 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
throw new IllegalArgumentException("Activity may not be null");
|
||||
}
|
||||
|
||||
int accentColor = ThemeUtils.primaryAccentColor(getContext());
|
||||
|
||||
parentFolder = arguments.getParcelable(ARG_PARENT_FOLDER);
|
||||
|
||||
// Inflate the layout for the dialog
|
||||
LayoutInflater inflater = activity.getLayoutInflater();
|
||||
@SuppressLint("InflateParams") View view = inflater.inflate(R.layout.choose_template, null);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
fileName.requestFocus();
|
||||
fileName.getBackground().setColorFilter(accentColor, PorterDuff.Mode.SRC_ATOP);
|
||||
|
||||
try {
|
||||
client = clientFactory.create(currentAccount.getUser());
|
||||
} catch (ClientFactory.CreationException e) {
|
||||
throw new RuntimeException(e); // we'll NPE without the client
|
||||
}
|
||||
|
||||
parentFolder = arguments.getParcelable(ARG_PARENT_FOLDER);
|
||||
|
||||
// Inflate the layout for the dialog
|
||||
LayoutInflater inflater = requireActivity().getLayoutInflater();
|
||||
binding = ChooseTemplateBinding.inflate(inflater, null, false);
|
||||
View view = binding.getRoot();
|
||||
|
||||
binding.filename.requestFocus();
|
||||
ThemeUtils.colorTextInput(binding.filenameContainer, binding.filename, ThemeUtils.primaryColor(getContext()));
|
||||
|
||||
Type type = Type.valueOf(arguments.getString(ARG_TYPE));
|
||||
new FetchTemplateTask(this, client).execute(type);
|
||||
|
||||
listView.setHasFixedSize(true);
|
||||
listView.setLayoutManager(new GridLayoutManager(activity, 2));
|
||||
binding.list.setHasFixedSize(true);
|
||||
binding.list.setLayoutManager(new GridLayoutManager(activity, 2));
|
||||
adapter = new RichDocumentsTemplateAdapter(type, this, getContext(), currentAccount, clientFactory);
|
||||
listView.setAdapter(adapter);
|
||||
binding.list.setAdapter(adapter);
|
||||
|
||||
// Build the dialog
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setView(view)
|
||||
.setNegativeButton(R.string.common_cancel, this)
|
||||
.setTitle(R.string.select_template);
|
||||
.setPositiveButton(R.string.create, null)
|
||||
.setNeutralButton(R.string.common_cancel, null)
|
||||
.setTitle(getTitle(type));
|
||||
Dialog dialog = builder.create();
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
|
@ -183,6 +180,24 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
return dialog;
|
||||
}
|
||||
|
||||
private int getTitle(Type type) {
|
||||
if (type == Type.DOCUMENT) {
|
||||
return R.string.create_new_document;
|
||||
} else if (type == Type.SPREADSHEET) {
|
||||
return R.string.create_new_spreadsheet;
|
||||
} else if (type == Type.PRESENTATION) {
|
||||
return R.string.create_new_presentation;
|
||||
}
|
||||
|
||||
return R.string.select_template;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
private void createFromTemplate(Template template, String path) {
|
||||
new CreateFileFromTemplateTask(this, client, template, path, currentAccount.getUser()).execute();
|
||||
}
|
||||
|
@ -193,22 +208,48 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Template template) {
|
||||
String name = fileName.getText().toString();
|
||||
public void onClick(View v) {
|
||||
String name = binding.filename.getText().toString();
|
||||
String path = parentFolder.getRemotePath() + name;
|
||||
|
||||
if (name.isEmpty() || name.equalsIgnoreCase(DOT + template.getExtension())) {
|
||||
DisplayUtils.showSnackMessage(listView, R.string.enter_filename);
|
||||
} else if (!name.endsWith(template.getExtension())) {
|
||||
createFromTemplate(template, path + DOT + template.getExtension());
|
||||
Template selectedTemplate = adapter.getSelectedTemplate();
|
||||
|
||||
if (selectedTemplate == null) {
|
||||
DisplayUtils.showSnackMessage(binding.list, R.string.select_one_template);
|
||||
} else if (name.isEmpty() || name.equalsIgnoreCase(DOT + selectedTemplate.getExtension())) {
|
||||
DisplayUtils.showSnackMessage(binding.list, R.string.enter_filename);
|
||||
} else if (!name.endsWith(selectedTemplate.getExtension())) {
|
||||
createFromTemplate(selectedTemplate, path + DOT + selectedTemplate.getExtension());
|
||||
} else {
|
||||
createFromTemplate(template, path);
|
||||
createFromTemplate(selectedTemplate, path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// cancel is handled by dialog itself, no other button available
|
||||
public void onClick(Template template) {
|
||||
onTemplateChosen(template);
|
||||
}
|
||||
|
||||
private void onTemplateChosen(Template template) {
|
||||
adapter.setTemplateAsActive(template);
|
||||
prefillFilenameIfEmpty(template);
|
||||
checkEnablingCreateButton();
|
||||
}
|
||||
|
||||
private void prefillFilenameIfEmpty(Template template) {
|
||||
String name = binding.filename.getText().toString();
|
||||
if (name.isEmpty() || name.equalsIgnoreCase(DOT + template.getExtension())) {
|
||||
binding.filename.setText(String.format("%s.%s", template.name, template.extension));
|
||||
}
|
||||
binding.filename.setSelection(binding.filename.getText().toString().lastIndexOf('.'));
|
||||
}
|
||||
|
||||
private void checkEnablingCreateButton() {
|
||||
Template selectedTemplate = adapter.getSelectedTemplate();
|
||||
String name = binding.filename.getText().toString();
|
||||
|
||||
positiveButton.setEnabled(selectedTemplate != null && !name.isEmpty() &&
|
||||
!name.equalsIgnoreCase(DOT + selectedTemplate.getExtension()));
|
||||
}
|
||||
|
||||
private static class CreateFileFromTemplateTask extends AsyncTask<Void, Void, String> {
|
||||
|
@ -268,7 +309,7 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
|
||||
if (fragment != null && fragment.isAdded()) {
|
||||
if (url.isEmpty()) {
|
||||
DisplayUtils.showSnackMessage(fragment.listView, "Error creating file from template");
|
||||
DisplayUtils.showSnackMessage(fragment.binding.list, "Error creating file from template");
|
||||
} else {
|
||||
Intent collaboraWebViewIntent = new Intent(MainApp.getAppContext(), RichDocumentsEditorWebView.class);
|
||||
collaboraWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_TITLE, "Collabora");
|
||||
|
@ -319,12 +360,18 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
|
||||
if (fragment != null) {
|
||||
if (templateList.isEmpty()) {
|
||||
DisplayUtils.showSnackMessage(fragment.listView, R.string.error_retrieving_templates);
|
||||
DisplayUtils.showSnackMessage(fragment.binding.list, R.string.error_retrieving_templates);
|
||||
} else {
|
||||
fragment.setTemplateList(templateList);
|
||||
if (templateList.size() == SINGLE_TEMPLATE) {
|
||||
fragment.onTemplateChosen(templateList.get(0));
|
||||
fragment.binding.list.setVisibility(View.GONE);
|
||||
} else {
|
||||
String name = DOT + templateList.get(0).getExtension();
|
||||
fragment.binding.filename.setText(name);
|
||||
fragment.binding.helperText.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
String name = DOT + templateList.get(0).getExtension();
|
||||
fragment.fileName.setText(name);
|
||||
fragment.setTemplateList(templateList);
|
||||
}
|
||||
} else {
|
||||
Log_OC.e(TAG, "Error streaming file: no previewMediaFragment!");
|
||||
|
|
|
@ -24,20 +24,19 @@
|
|||
|
||||
package com.owncloud.android.ui.dialog;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.nextcloud.android.lib.resources.directediting.DirectEditingCreateFileRemoteOperation;
|
||||
import com.nextcloud.android.lib.resources.directediting.DirectEditingObtainListOfTemplatesRemoteOperation;
|
||||
|
@ -47,6 +46,7 @@ import com.nextcloud.client.di.Injectable;
|
|||
import com.nextcloud.client.network.ClientFactory;
|
||||
import com.owncloud.android.MainApp;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.databinding.ChooseTemplateBinding;
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.lib.common.Creator;
|
||||
|
@ -72,26 +72,27 @@ import androidx.annotation.NonNull;
|
|||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
/**
|
||||
* Dialog to show templates for new documents/spreadsheets/presentations.
|
||||
*/
|
||||
public class ChooseTemplateDialogFragment extends DialogFragment implements DialogInterface.OnClickListener,
|
||||
public class ChooseTemplateDialogFragment extends DialogFragment implements View.OnClickListener,
|
||||
TemplateAdapter.ClickListener, Injectable {
|
||||
|
||||
private static final String ARG_PARENT_FOLDER = "PARENT_FOLDER";
|
||||
private static final String ARG_CREATOR = "CREATOR";
|
||||
private static final String ARG_HEADLINE = "HEADLINE";
|
||||
private static final String TAG = ChooseTemplateDialogFragment.class.getSimpleName();
|
||||
private static final String DOT = ".";
|
||||
public static final int SINGLE_TEMPLATE = 1;
|
||||
|
||||
private TemplateAdapter adapter;
|
||||
private OCFile parentFolder;
|
||||
private String title;
|
||||
@Inject ClientFactory clientFactory;
|
||||
private Creator creator;
|
||||
@Inject CurrentAccountProvider currentAccount;
|
||||
private Button positiveButton;
|
||||
|
||||
public enum Type {
|
||||
DOCUMENT,
|
||||
|
@ -99,20 +100,16 @@ public class ChooseTemplateDialogFragment extends DialogFragment implements Dial
|
|||
PRESENTATION
|
||||
}
|
||||
|
||||
@BindView(R.id.list)
|
||||
RecyclerView listView;
|
||||
ChooseTemplateBinding binding;
|
||||
|
||||
@BindView(R.id.filename)
|
||||
EditText fileName;
|
||||
|
||||
public static ChooseTemplateDialogFragment newInstance(OCFile parentFolder, Creator creator) {
|
||||
public static ChooseTemplateDialogFragment newInstance(OCFile parentFolder, Creator creator, String headline) {
|
||||
ChooseTemplateDialogFragment frag = new ChooseTemplateDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putParcelable(ARG_PARENT_FOLDER, parentFolder);
|
||||
args.putParcelable(ARG_CREATOR, creator);
|
||||
args.putString(ARG_HEADLINE, headline);
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -123,8 +120,14 @@ public class ChooseTemplateDialogFragment extends DialogFragment implements Dial
|
|||
|
||||
AlertDialog alertDialog = (AlertDialog) getDialog();
|
||||
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(color);
|
||||
alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(color);
|
||||
positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
ThemeUtils.themeBorderlessButton(positiveButton, color);
|
||||
positiveButton.setOnClickListener(this);
|
||||
positiveButton.setEnabled(false);
|
||||
|
||||
ThemeUtils.themeBorderlessButton(alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL), color);
|
||||
|
||||
checkEnablingCreateButton();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -140,18 +143,45 @@ public class ChooseTemplateDialogFragment extends DialogFragment implements Dial
|
|||
throw new IllegalArgumentException("Activity may not be null");
|
||||
}
|
||||
|
||||
int accentColor = ThemeUtils.primaryAccentColor(getContext());
|
||||
|
||||
parentFolder = arguments.getParcelable(ARG_PARENT_FOLDER);
|
||||
creator = arguments.getParcelable(ARG_CREATOR);
|
||||
title = arguments.getString(ARG_HEADLINE, getString(R.string.select_template));
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
title = arguments.getString(ARG_HEADLINE);
|
||||
} else {
|
||||
title = savedInstanceState.getString(ARG_HEADLINE);
|
||||
}
|
||||
|
||||
// Inflate the layout for the dialog
|
||||
LayoutInflater inflater = activity.getLayoutInflater();
|
||||
@SuppressLint("InflateParams") View view = inflater.inflate(R.layout.choose_template, null);
|
||||
ButterKnife.bind(this, view);
|
||||
LayoutInflater inflater = requireActivity().getLayoutInflater();
|
||||
binding = ChooseTemplateBinding.inflate(inflater, null, false);
|
||||
View view = binding.getRoot();
|
||||
|
||||
fileName.requestFocus();
|
||||
fileName.getBackground().setColorFilter(accentColor, PorterDuff.Mode.SRC_ATOP);
|
||||
binding.filename.requestFocus();
|
||||
ThemeUtils.colorTextInput(binding.filenameContainer, binding.filename, ThemeUtils.primaryColor(getContext()));
|
||||
|
||||
binding.filename.setOnKeyListener((v, keyCode, event) -> {
|
||||
checkEnablingCreateButton();
|
||||
return false;
|
||||
});
|
||||
|
||||
binding.filename.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
// generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
// generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
checkEnablingCreateButton();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
User user = currentAccount.getUser();
|
||||
|
@ -160,16 +190,17 @@ public class ChooseTemplateDialogFragment extends DialogFragment implements Dial
|
|||
Log_OC.e(TAG, "Loading stream url not possible: " + e);
|
||||
}
|
||||
|
||||
listView.setHasFixedSize(true);
|
||||
listView.setLayoutManager(new GridLayoutManager(activity, 2));
|
||||
binding.list.setHasFixedSize(true);
|
||||
binding.list.setLayoutManager(new GridLayoutManager(activity, 2));
|
||||
adapter = new TemplateAdapter(creator.getMimetype(), this, getContext(), currentAccount, clientFactory);
|
||||
listView.setAdapter(adapter);
|
||||
binding.list.setAdapter(adapter);
|
||||
|
||||
// Build the dialog
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setView(view)
|
||||
.setNegativeButton(R.string.common_cancel, this)
|
||||
.setTitle(R.string.select_template);
|
||||
.setPositiveButton(R.string.create, null)
|
||||
.setNeutralButton(R.string.common_cancel, null)
|
||||
.setTitle(title);
|
||||
Dialog dialog = builder.create();
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
|
@ -181,6 +212,18 @@ public class ChooseTemplateDialogFragment extends DialogFragment implements Dial
|
|||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
|
||||
super.onSaveInstanceState(savedInstanceState);
|
||||
savedInstanceState.putString(ARG_HEADLINE, title);
|
||||
}
|
||||
|
||||
private void createFromTemplate(Template template, String path) {
|
||||
new CreateFileFromTemplateTask(this, clientFactory, currentAccount.getUser(), template, path, creator).execute();
|
||||
}
|
||||
|
@ -192,21 +235,47 @@ public class ChooseTemplateDialogFragment extends DialogFragment implements Dial
|
|||
|
||||
@Override
|
||||
public void onClick(Template template) {
|
||||
String name = fileName.getText().toString();
|
||||
String path = parentFolder.getRemotePath() + name;
|
||||
onTemplateChosen(template);
|
||||
}
|
||||
|
||||
private void onTemplateChosen(Template template) {
|
||||
adapter.setTemplateAsActive(template);
|
||||
prefillFilenameIfEmpty(template);
|
||||
checkEnablingCreateButton();
|
||||
}
|
||||
|
||||
private void prefillFilenameIfEmpty(Template template) {
|
||||
String name = binding.filename.getText().toString();
|
||||
if (name.isEmpty() || name.equalsIgnoreCase(DOT + template.getExtension())) {
|
||||
DisplayUtils.showSnackMessage(listView, R.string.enter_filename);
|
||||
} else if (!name.endsWith(template.getExtension())) {
|
||||
createFromTemplate(template, path + DOT + template.getExtension());
|
||||
} else {
|
||||
createFromTemplate(template, path);
|
||||
binding.filename.setText(String.format("%s.%s", template.title, template.extension));
|
||||
}
|
||||
binding.filename.setSelection(binding.filename.getText().toString().lastIndexOf('.'));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// cancel is handled by dialog itself, no other button available
|
||||
public void onClick(View v) {
|
||||
String name = binding.filename.getText().toString();
|
||||
String path = parentFolder.getRemotePath() + name;
|
||||
|
||||
Template selectedTemplate = adapter.getSelectedTemplate();
|
||||
|
||||
if (selectedTemplate == null) {
|
||||
DisplayUtils.showSnackMessage(binding.list, R.string.select_one_template);
|
||||
} else if (name.isEmpty() || name.equalsIgnoreCase(DOT + selectedTemplate.getExtension())) {
|
||||
DisplayUtils.showSnackMessage(binding.list, R.string.enter_filename);
|
||||
} else if (!name.endsWith(selectedTemplate.getExtension())) {
|
||||
createFromTemplate(selectedTemplate, path + DOT + selectedTemplate.getExtension());
|
||||
} else {
|
||||
createFromTemplate(selectedTemplate, path);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkEnablingCreateButton() {
|
||||
Template selectedTemplate = adapter.getSelectedTemplate();
|
||||
String name = binding.filename.getText().toString();
|
||||
|
||||
positiveButton.setEnabled(selectedTemplate != null && !name.isEmpty() &&
|
||||
!name.equalsIgnoreCase(DOT + selectedTemplate.getExtension()));
|
||||
}
|
||||
|
||||
private static class CreateFileFromTemplateTask extends AsyncTask<Void, Void, String> {
|
||||
|
@ -284,7 +353,7 @@ public class ChooseTemplateDialogFragment extends DialogFragment implements Dial
|
|||
|
||||
if (fragment != null && fragment.isAdded()) {
|
||||
if (url.isEmpty()) {
|
||||
DisplayUtils.showSnackMessage(fragment.listView, "Error creating file from template");
|
||||
DisplayUtils.showSnackMessage(fragment.binding.list, "Error creating file from template");
|
||||
} else {
|
||||
Intent editorWebView = new Intent(MainApp.getAppContext(), TextEditorWebView.class);
|
||||
editorWebView.putExtra(ExternalSiteWebView.EXTRA_TITLE, "Text");
|
||||
|
@ -345,12 +414,18 @@ public class ChooseTemplateDialogFragment extends DialogFragment implements Dial
|
|||
|
||||
if (fragment != null && fragment.isAdded()) {
|
||||
if (templateList.templates.isEmpty()) {
|
||||
DisplayUtils.showSnackMessage(fragment.listView, R.string.error_retrieving_templates);
|
||||
DisplayUtils.showSnackMessage(fragment.binding.list, R.string.error_retrieving_templates);
|
||||
} else {
|
||||
fragment.setTemplateList(templateList);
|
||||
if (templateList.templates.size() == SINGLE_TEMPLATE) {
|
||||
fragment.onTemplateChosen(templateList.templates.values().iterator().next());
|
||||
fragment.binding.list.setVisibility(View.GONE);
|
||||
} else {
|
||||
String name = DOT + templateList.templates.values().iterator().next().getExtension();
|
||||
fragment.binding.filename.setText(name);
|
||||
fragment.binding.helperText.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
String name = DOT + templateList.templates.values().iterator().next().getExtension();
|
||||
fragment.fileName.setText(name);
|
||||
fragment.setTemplateList(templateList);
|
||||
}
|
||||
} else {
|
||||
Log_OC.e(TAG, "Error streaming file: no previewMediaFragment!");
|
||||
|
|
|
@ -202,10 +202,10 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment {
|
|||
mNameCollisionPolicySummary = view.findViewById(R.id.setting_instant_name_collision_policy_summary);
|
||||
|
||||
mCancel = view.findViewById(R.id.cancel);
|
||||
ThemeUtils.themeDialogActionButton(mCancel);
|
||||
ThemeUtils.themeBorderlessButton(mCancel, accentColor);
|
||||
|
||||
mSave = view.findViewById(R.id.save);
|
||||
ThemeUtils.themeDialogActionButton(mSave);
|
||||
ThemeUtils.themeBorderlessButton(mSave, accentColor);
|
||||
|
||||
// Set values
|
||||
setEnabled(mSyncedFolder.isEnabled());
|
||||
|
|
|
@ -65,7 +65,7 @@ public interface OCFileListBottomSheetActions {
|
|||
/**
|
||||
* open template selection for creator @link Creator
|
||||
*/
|
||||
void showTemplate(Creator creator);
|
||||
void showTemplate(Creator creator, String headline);
|
||||
|
||||
/**
|
||||
* open editor for rich workspace
|
||||
|
|
|
@ -121,7 +121,7 @@ public class OCFileListBottomSheetDialog extends BottomSheetDialog {
|
|||
getContext()));
|
||||
|
||||
creatorView.setOnClickListener(v -> {
|
||||
actions.showTemplate(creator);
|
||||
actions.showTemplate(creator, creatorViewBinding.creatorName.getText().toString());
|
||||
dismiss();
|
||||
});
|
||||
|
||||
|
|
|
@ -565,8 +565,8 @@ public class OCFileListFragment extends ExtendedListFragment implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void showTemplate(Creator creator) {
|
||||
ChooseTemplateDialogFragment.newInstance(mFile, creator).show(requireActivity().getSupportFragmentManager(),
|
||||
public void showTemplate(Creator creator, String headline) {
|
||||
ChooseTemplateDialogFragment.newInstance(mFile, creator, headline).show(requireActivity().getSupportFragmentManager(),
|
||||
DIALOG_CREATE_DOCUMENT);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ import android.widget.ImageView;
|
|||
import android.widget.ProgressBar;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
@ -569,13 +568,12 @@ public final class ThemeUtils {
|
|||
));
|
||||
}
|
||||
|
||||
public static void themeDialogActionButton(MaterialButton button) {
|
||||
public static void themeBorderlessButton(Button button, int primaryColor) {
|
||||
if (button == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Context context = button.getContext();
|
||||
int accentColor = ThemeUtils.primaryAccentColor(button.getContext());
|
||||
int disabledColor = ContextCompat.getColor(context, R.color.disabled_text);
|
||||
button.setTextColor(new ColorStateList(
|
||||
new int[][]{
|
||||
|
@ -583,7 +581,7 @@ public final class ThemeUtils {
|
|||
new int[]{-android.R.attr.state_enabled}, // disabled
|
||||
},
|
||||
new int[]{
|
||||
accentColor,
|
||||
primaryColor,
|
||||
disabledColor
|
||||
}
|
||||
));
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
Nextcloud Android client application
|
||||
|
||||
@author Tobias Kaminsky
|
||||
@author Andy Scherzinger
|
||||
Copyright (C) 2020 Andy Scherzinger
|
||||
Copyright (C) 2018 Tobias Kaminsky
|
||||
Copyright (C) 2018 Nextcloud GmbH.
|
||||
|
||||
|
@ -20,11 +22,22 @@
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="clip_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/standard_padding">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="clip_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/standard_padding"
|
||||
android:paddingEnd="@dimen/standard_padding">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/helper_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/standard_half_padding"
|
||||
android:paddingEnd="@dimen/standard_half_padding"
|
||||
android:text="@string/choose_template_helper_text"
|
||||
android:textColor="@color/secondary_text_color"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list"
|
||||
|
@ -32,11 +45,24 @@
|
|||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/filename"
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/filename_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/filename_hint"
|
||||
android:inputType="text"
|
||||
android:importantForAutofill="no" />
|
||||
android:paddingTop="@dimen/standard_padding">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/filename"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:gravity="top"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="text"
|
||||
android:scrollbars="vertical">
|
||||
|
||||
</com.google.android.material.textfield.TextInputEditText>
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
Nextcloud Android client application
|
||||
|
||||
@author Tobias Kaminsky
|
||||
@author Andy Scherzinger
|
||||
Copyright (C) 2020 Andy Scherzinger
|
||||
Copyright (C) 2018 Tobias Kaminsky
|
||||
Copyright (C) 2018 Nextcloud GmbH.
|
||||
|
||||
|
@ -19,25 +21,35 @@
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/standard_padding"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/standard_padding">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/thumbnail"
|
||||
android:layout_width="@dimen/share_icon_size"
|
||||
android:layout_height="@dimen/share_icon_size"
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/template_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:contentDescription="@string/thumbnail"
|
||||
android:src="@drawable/file_doc"/>
|
||||
app:cardElevation="0dp"
|
||||
app:strokeColor="@color/grey_200"
|
||||
app:strokeWidth="2dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/template"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="84dp"
|
||||
android:layout_margin="@dimen/standard_margin"
|
||||
android:contentDescription="@string/thumbnail"
|
||||
android:src="@drawable/file_doc" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:id="@+id/template_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -45,5 +57,5 @@
|
|||
android:gravity="center_horizontal"
|
||||
android:paddingTop="@dimen/standard_half_padding"
|
||||
android:textColor="@color/text_color"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
tools:text="Template" />
|
||||
</LinearLayout>
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
<color name="text_color">#E3E3E3</color>
|
||||
<color name="text_color_inverse">#000000</color>
|
||||
<color name="disabled_text">#ff6F6F6F</color>
|
||||
<color name="secondary_text_color">#A5A5A5</color>
|
||||
<color name="list_divider_background">#222222</color>
|
||||
|
||||
|
|
|
@ -954,4 +954,7 @@
|
|||
<string name="direct_login_failed">Login via direct link failed!</string>
|
||||
<string name="login_url_helper_text">The link to your %1$s web interface when you open it in the browser.</string>
|
||||
<string name="brute_force_delay">Delayed due to too many wrong attempts</string>
|
||||
<string name="create">Create</string>
|
||||
<string name="select_one_template">Please select one template</string>
|
||||
<string name="choose_template_helper_text">Please choose a template and enter a file name.</string>
|
||||
</resources>
|
||||
|
|