Merge pull request #10307 from nextcloud/fix/choosetemplate-button-nullpointer

Fix NPE in ChooseTemplateDialogFragment
This commit is contained in:
Tobias Kaminsky 2022-06-03 07:29:32 +02:00 committed by GitHub
commit 3fd8928327
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 412 additions and 452 deletions

View file

@ -1,451 +0,0 @@
/*
* Nextcloud Android client application
*
* @author Tobias Kaminsky
* @author Chris Narkiewicz
*
* Copyright (C) 2018 Tobias Kaminsky
* Copyright (C) 2018 Nextcloud GmbH.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.owncloud.android.ui.dialog;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
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.Button;
import com.nextcloud.android.lib.resources.directediting.DirectEditingCreateFileRemoteOperation;
import com.nextcloud.android.lib.resources.directediting.DirectEditingObtainListOfTemplatesRemoteOperation;
import com.nextcloud.client.account.CurrentAccountProvider;
import com.nextcloud.client.account.User;
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;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.Template;
import com.owncloud.android.lib.common.TemplateList;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation;
import com.owncloud.android.lib.resources.files.model.RemoteFile;
import com.owncloud.android.ui.activity.ExternalSiteWebView;
import com.owncloud.android.ui.activity.TextEditorWebView;
import com.owncloud.android.ui.adapter.TemplateAdapter;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.theme.ThemeButtonUtils;
import com.owncloud.android.utils.theme.ThemeColorUtils;
import com.owncloud.android.utils.theme.ThemeDrawableUtils;
import com.owncloud.android.utils.theme.ThemeTextInputUtils;
import java.lang.ref.WeakReference;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.GridLayoutManager;
/**
* Dialog to show templates for new documents/spreadsheets/presentations.
*/
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;
@Inject ClientFactory clientFactory;
@Inject CurrentAccountProvider currentAccount;
@Inject ThemeColorUtils themeColorUtils;
@Inject ThemeDrawableUtils themeDrawableUtils;
@Inject ThemeButtonUtils themeButtonUtils;
@Inject ThemeTextInputUtils themeTextInputUtils;
private TemplateAdapter adapter;
private OCFile parentFolder;
private String title;
private Button positiveButton;
private Creator creator;
public enum Type {
DOCUMENT,
SPREADSHEET,
PRESENTATION
}
ChooseTemplateBinding binding;
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
public void onStart() {
super.onStart();
AlertDialog alertDialog = (AlertDialog) getDialog();
positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
themeButtonUtils.themeBorderlessButton(themeColorUtils,
positiveButton,
alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL));
positiveButton.setOnClickListener(this);
positiveButton.setEnabled(false);
checkEnablingCreateButton();
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle arguments = getArguments();
if (arguments == null) {
throw new IllegalArgumentException("Arguments may not be null");
}
Activity activity = getActivity();
if (activity == null) {
throw new IllegalArgumentException("Activity may not be null");
}
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 = requireActivity().getLayoutInflater();
binding = ChooseTemplateBinding.inflate(inflater, null, false);
View view = binding.getRoot();
binding.filename.requestFocus();
themeTextInputUtils.colorTextInput(binding.filenameContainer,
binding.filename,
themeColorUtils.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();
new FetchTemplateTask(this, clientFactory, user, creator).execute();
} catch (Exception e) {
Log_OC.e(TAG, "Loading stream url not possible: " + e);
}
binding.list.setHasFixedSize(true);
binding.list.setLayoutManager(new GridLayoutManager(activity, 2));
adapter = new TemplateAdapter(creator.getMimetype(),
this,
getContext(),
currentAccount,
clientFactory,
themeColorUtils,
themeDrawableUtils);
binding.list.setAdapter(adapter);
// Build the dialog
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setView(view)
.setPositiveButton(R.string.create, null)
.setNeutralButton(R.string.common_cancel, null)
.setTitle(title);
Dialog dialog = builder.create();
Window window = dialog.getWindow();
if (window != null) {
window.setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}
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();
}
public void setTemplateList(TemplateList templateList) {
adapter.setTemplateList(templateList);
adapter.notifyDataSetChanged();
}
@Override
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.getTitle(), template.getExtension()));
name = binding.filename.getText().toString();
int dotPos = name.lastIndexOf('.');
binding.filename.setSelection((dotPos != -1) ? dotPos : name.length());
}
}
@Override
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> {
private ClientFactory clientFactory;
private WeakReference<ChooseTemplateDialogFragment> chooseTemplateDialogFragmentWeakReference;
private Template template;
private String path;
private Creator creator;
private User user;
private OCFile file;
CreateFileFromTemplateTask(ChooseTemplateDialogFragment chooseTemplateDialogFragment,
ClientFactory clientFactory,
User user,
Template template,
String path,
Creator creator
) {
this.clientFactory = clientFactory;
this.chooseTemplateDialogFragmentWeakReference = new WeakReference<>(chooseTemplateDialogFragment);
this.template = template;
this.path = path;
this.creator = creator;
this.user = user;
}
@Override
protected String doInBackground(Void... voids) {
try {
OwnCloudClient client = clientFactory.create(user);
RemoteOperationResult<String> result =
new DirectEditingCreateFileRemoteOperation(path,
creator.getEditor(),
creator.getId(),
template.getTitle()).execute(client);
if (!result.isSuccess()) {
return "";
}
RemoteOperationResult newFileResult = new ReadFileRemoteOperation(path).execute(client);
if (!newFileResult.isSuccess()) {
return "";
}
final ChooseTemplateDialogFragment fragment = chooseTemplateDialogFragmentWeakReference.get();
if (fragment == null) {
return "";
}
final Context context = fragment.getContext();
if (context == null) {
// fragment has been detached
return "";
}
FileDataStorageManager storageManager = new FileDataStorageManager(user,
context.getContentResolver());
OCFile temp = FileStorageUtils.fillOCFile((RemoteFile) newFileResult.getData().get(0));
storageManager.saveFile(temp);
file = storageManager.getFileByPath(path);
return result.getResultData();
} catch (ClientFactory.CreationException e) {
Log_OC.e(TAG, "Error creating file from template!", e);
return "";
}
}
@Override
protected void onPostExecute(String url) {
final ChooseTemplateDialogFragment fragment = chooseTemplateDialogFragmentWeakReference.get();
if (fragment != null && fragment.isAdded()) {
if (url.isEmpty()) {
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");
editorWebView.putExtra(ExternalSiteWebView.EXTRA_URL, url);
editorWebView.putExtra(ExternalSiteWebView.EXTRA_FILE, file);
editorWebView.putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, false);
fragment.startActivity(editorWebView);
fragment.dismiss();
}
} else {
Log_OC.e(TAG, "Error creating file from template!");
}
}
}
private static class FetchTemplateTask extends AsyncTask<Void, Void, TemplateList> {
private User user;
private ClientFactory clientFactory;
private WeakReference<ChooseTemplateDialogFragment> chooseTemplateDialogFragmentWeakReference;
private Creator creator;
FetchTemplateTask(ChooseTemplateDialogFragment chooseTemplateDialogFragment,
ClientFactory clientFactory,
User user,
Creator creator) {
this.user = user;
this.clientFactory = clientFactory;
this.chooseTemplateDialogFragmentWeakReference = new WeakReference<>(chooseTemplateDialogFragment);
this.creator = creator;
}
@Override
protected TemplateList doInBackground(Void... voids) {
try {
OwnCloudClient client = clientFactory.create(user);
RemoteOperationResult<TemplateList> result =
new DirectEditingObtainListOfTemplatesRemoteOperation(creator.getEditor(),
creator.getId())
.execute(client);
if (!result.isSuccess()) {
return new TemplateList();
}
return result.getResultData();
} catch (ClientFactory.CreationException e) {
Log_OC.e(TAG, "Could not fetch template", e);
return new TemplateList();
}
}
@Override
protected void onPostExecute(TemplateList templateList) {
ChooseTemplateDialogFragment fragment = chooseTemplateDialogFragmentWeakReference.get();
if (fragment != null && fragment.isAdded()) {
if (templateList.getTemplates().isEmpty()) {
DisplayUtils.showSnackMessage(fragment.binding.list, R.string.error_retrieving_templates);
} else {
if (templateList.getTemplates().size() == SINGLE_TEMPLATE) {
fragment.onTemplateChosen(templateList.getTemplates().values().iterator().next());
fragment.binding.list.setVisibility(View.GONE);
} else {
String name = DOT + templateList.getTemplates().values().iterator().next().getExtension();
fragment.binding.filename.setText(name);
fragment.binding.helperText.setVisibility(View.VISIBLE);
}
fragment.setTemplateList(templateList);
}
} else {
Log_OC.e(TAG, "Error streaming file: no previewMediaFragment!");
}
}
}
}

View file

@ -0,0 +1,411 @@
/*
* Nextcloud Android client application
*
* @author Tobias Kaminsky
* @author Chris Narkiewicz
*
* Copyright (C) 2018 Tobias Kaminsky
* Copyright (C) 2018 Nextcloud GmbH.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.owncloud.android.ui.dialog
import android.app.Dialog
import android.content.Intent
import android.os.AsyncTask
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.WindowManager
import android.widget.Button
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.GridLayoutManager
import com.nextcloud.android.lib.resources.directediting.DirectEditingCreateFileRemoteOperation
import com.nextcloud.android.lib.resources.directediting.DirectEditingObtainListOfTemplatesRemoteOperation
import com.nextcloud.client.account.CurrentAccountProvider
import com.nextcloud.client.account.User
import com.nextcloud.client.di.Injectable
import com.nextcloud.client.network.ClientFactory
import com.nextcloud.client.network.ClientFactory.CreationException
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
import com.owncloud.android.lib.common.Template
import com.owncloud.android.lib.common.TemplateList
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation
import com.owncloud.android.lib.resources.files.model.RemoteFile
import com.owncloud.android.ui.activity.ExternalSiteWebView
import com.owncloud.android.ui.activity.TextEditorWebView
import com.owncloud.android.ui.adapter.TemplateAdapter
import com.owncloud.android.utils.DisplayUtils
import com.owncloud.android.utils.FileStorageUtils
import com.owncloud.android.utils.theme.ThemeButtonUtils
import com.owncloud.android.utils.theme.ThemeColorUtils
import com.owncloud.android.utils.theme.ThemeDrawableUtils
import com.owncloud.android.utils.theme.ThemeTextInputUtils
import java.lang.ref.WeakReference
import javax.inject.Inject
/**
* Dialog to show templates for new documents/spreadsheets/presentations.
*/
class ChooseTemplateDialogFragment : DialogFragment(), View.OnClickListener, TemplateAdapter.ClickListener, Injectable {
@Inject
lateinit var clientFactory: ClientFactory
@Inject
lateinit var currentAccount: CurrentAccountProvider
@Inject
lateinit var themeColorUtils: ThemeColorUtils
@Inject
lateinit var themeDrawableUtils: ThemeDrawableUtils
@Inject
lateinit var themeButtonUtils: ThemeButtonUtils
@Inject
lateinit var themeTextInputUtils: ThemeTextInputUtils
private var adapter: TemplateAdapter? = null
private var parentFolder: OCFile? = null
private var title: String? = null
private var positiveButton: Button? = null
private var creator: Creator? = null
enum class Type {
DOCUMENT, SPREADSHEET, PRESENTATION
}
private var _binding: ChooseTemplateBinding? = null
private val binding get() = _binding!!
override fun onStart() {
super.onStart()
val alertDialog = dialog as AlertDialog
val button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)
themeButtonUtils.themeBorderlessButton(
themeColorUtils,
button,
alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL)
)
button.setOnClickListener(this)
button.isEnabled = false
positiveButton = button
checkEnablingCreateButton()
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val arguments = arguments ?: throw IllegalArgumentException("Arguments may not be null")
val activity = activity ?: throw IllegalArgumentException("Activity may not be null")
parentFolder = arguments.getParcelable(ARG_PARENT_FOLDER)
creator = arguments.getParcelable(ARG_CREATOR)
title = arguments.getString(ARG_HEADLINE, getString(R.string.select_template))
title = when (savedInstanceState) {
null -> arguments.getString(ARG_HEADLINE)
else -> savedInstanceState.getString(ARG_HEADLINE)
}
// Inflate the layout for the dialog
val inflater = requireActivity().layoutInflater
_binding = ChooseTemplateBinding.inflate(inflater, null, false)
val view: View = binding.root
binding.filename.requestFocus()
themeTextInputUtils.colorTextInput(
binding.filenameContainer,
binding.filename,
themeColorUtils.primaryColor(context)
)
binding.filename.setOnKeyListener { _, _, _ ->
checkEnablingCreateButton()
false
}
binding.filename.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) = Unit
override fun afterTextChanged(s: Editable) {
checkEnablingCreateButton()
}
})
fetchTemplate()
binding.list.setHasFixedSize(true)
binding.list.layoutManager = GridLayoutManager(activity, 2)
adapter = TemplateAdapter(
creator!!.mimetype,
this,
context,
currentAccount,
clientFactory,
themeColorUtils,
themeDrawableUtils
)
binding.list.adapter = adapter
// Build the dialog
val builder = AlertDialog.Builder(activity)
builder.setView(view)
.setPositiveButton(R.string.create, null)
.setNeutralButton(R.string.common_cancel, null)
.setTitle(title)
val dialog: Dialog = builder.create()
val window = dialog.window
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
return dialog
}
@Suppress("TooGenericExceptionCaught") // legacy code
private fun fetchTemplate() {
try {
val user = currentAccount.user
FetchTemplateTask(this, clientFactory, user, creator).execute()
} catch (e: Exception) {
Log_OC.e(TAG, "Loading stream url not possible: $e")
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putString(ARG_HEADLINE, title)
}
private fun createFromTemplate(template: Template, path: String) {
CreateFileFromTemplateTask(this, clientFactory, currentAccount.user, template, path, creator).execute()
}
fun setTemplateList(templateList: TemplateList?) {
adapter!!.setTemplateList(templateList)
adapter!!.notifyDataSetChanged()
}
override fun onClick(template: Template) {
onTemplateChosen(template)
}
private fun onTemplateChosen(template: Template) {
adapter!!.setTemplateAsActive(template)
prefillFilenameIfEmpty(template)
checkEnablingCreateButton()
}
private fun prefillFilenameIfEmpty(template: Template) {
var name = binding.filename.text.toString()
if (name.isEmpty() || name.equals(DOT + template.extension, ignoreCase = true)) {
binding.filename.setText(String.format("%s.%s", template.title, template.extension))
name = binding.filename.text.toString()
val dotPos = name.lastIndexOf('.')
binding.filename.setSelection(if (dotPos != -1) dotPos else name.length)
}
}
override fun onClick(v: View) {
val name = binding.filename.text.toString()
val path = parentFolder!!.remotePath + name
val selectedTemplate = adapter!!.selectedTemplate
if (selectedTemplate == null) {
DisplayUtils.showSnackMessage(binding.list, R.string.select_one_template)
} else if (name.isEmpty() || name.equals(DOT + selectedTemplate.extension, ignoreCase = true)) {
DisplayUtils.showSnackMessage(binding.list, R.string.enter_filename)
} else if (!name.endsWith(selectedTemplate.extension)) {
createFromTemplate(selectedTemplate, path + DOT + selectedTemplate.extension)
} else {
createFromTemplate(selectedTemplate, path)
}
}
private fun checkEnablingCreateButton() {
if (positiveButton != null) {
val selectedTemplate = adapter!!.selectedTemplate
val name = binding.filename.text.toString()
positiveButton!!.isEnabled = selectedTemplate != null && name.isNotEmpty() &&
!name.equals(DOT + selectedTemplate.extension, ignoreCase = true)
}
}
@Suppress("LongParameterList") // legacy code
private class CreateFileFromTemplateTask(
chooseTemplateDialogFragment: ChooseTemplateDialogFragment,
private val clientFactory: ClientFactory?,
user: User,
template: Template,
path: String,
creator: Creator?
) : AsyncTask<Void, Void, String>() {
private val chooseTemplateDialogFragmentWeakReference: WeakReference<ChooseTemplateDialogFragment>
private val template: Template
private val path: String
private val creator: Creator?
private val user: User
private var file: OCFile? = null
@Suppress("ReturnCount") // legacy code
override fun doInBackground(vararg params: Void): String {
return try {
val client = clientFactory!!.create(user)
val result = DirectEditingCreateFileRemoteOperation(
path,
creator!!.editor,
creator.id,
template.title
).execute(client)
if (!result.isSuccess) {
return ""
}
val newFileResult = ReadFileRemoteOperation(path).execute(client)
if (!newFileResult.isSuccess) {
return ""
}
val fragment = chooseTemplateDialogFragmentWeakReference.get() ?: return ""
val context = fragment.context
?: // fragment has been detached
return ""
val storageManager = FileDataStorageManager(
user,
context.contentResolver
)
val temp = FileStorageUtils.fillOCFile(newFileResult.data[0] as RemoteFile)
storageManager.saveFile(temp)
file = storageManager.getFileByPath(path)
result.resultData
} catch (e: CreationException) {
Log_OC.e(TAG, "Error creating file from template!", e)
""
}
}
override fun onPostExecute(url: String) {
val fragment = chooseTemplateDialogFragmentWeakReference.get()
if (fragment != null && fragment.isAdded) {
if (url.isEmpty()) {
DisplayUtils.showSnackMessage(fragment.binding.list, "Error creating file from template")
} else {
val editorWebView = Intent(MainApp.getAppContext(), TextEditorWebView::class.java)
editorWebView.putExtra(ExternalSiteWebView.EXTRA_TITLE, "Text")
editorWebView.putExtra(ExternalSiteWebView.EXTRA_URL, url)
editorWebView.putExtra(ExternalSiteWebView.EXTRA_FILE, file)
editorWebView.putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, false)
fragment.startActivity(editorWebView)
fragment.dismiss()
}
} else {
Log_OC.e(TAG, "Error creating file from template!")
}
}
init {
chooseTemplateDialogFragmentWeakReference = WeakReference(chooseTemplateDialogFragment)
this.template = template
this.path = path
this.creator = creator
this.user = user
}
}
private class FetchTemplateTask(
chooseTemplateDialogFragment: ChooseTemplateDialogFragment,
private val clientFactory: ClientFactory?,
private val user: User,
creator: Creator?
) : AsyncTask<Void, Void, TemplateList>() {
private val chooseTemplateDialogFragmentWeakReference: WeakReference<ChooseTemplateDialogFragment>
private val creator: Creator?
override fun doInBackground(vararg voids: Void): TemplateList {
return try {
val client = clientFactory!!.create(user)
val result = DirectEditingObtainListOfTemplatesRemoteOperation(
creator!!.editor,
creator.id
)
.execute(client)
if (!result.isSuccess) {
TemplateList()
} else result.resultData
} catch (e: CreationException) {
Log_OC.e(TAG, "Could not fetch template", e)
TemplateList()
}
}
override fun onPostExecute(templateList: TemplateList) {
val fragment = chooseTemplateDialogFragmentWeakReference.get()
if (fragment != null && fragment.isAdded) {
if (templateList.templates.isEmpty()) {
DisplayUtils.showSnackMessage(fragment.binding.list, R.string.error_retrieving_templates)
} else {
if (templateList.templates.size == SINGLE_TEMPLATE) {
fragment.onTemplateChosen(templateList.templates.values.iterator().next())
fragment.binding.list.visibility = View.GONE
} else {
val name = DOT + templateList.templates.values.iterator().next().extension
fragment.binding.filename.setText(name)
fragment.binding.helperText.visibility = View.VISIBLE
}
fragment.setTemplateList(templateList)
}
} else {
Log_OC.e(TAG, "Error streaming file: no previewMediaFragment!")
}
}
init {
chooseTemplateDialogFragmentWeakReference = WeakReference(chooseTemplateDialogFragment)
this.creator = creator
}
}
companion object {
private const val ARG_PARENT_FOLDER = "PARENT_FOLDER"
private const val ARG_CREATOR = "CREATOR"
private const val ARG_HEADLINE = "HEADLINE"
private val TAG = ChooseTemplateDialogFragment::class.java.simpleName
private const val DOT = "."
const val SINGLE_TEMPLATE = 1
@JvmStatic
fun newInstance(parentFolder: OCFile?, creator: Creator?, headline: String?): ChooseTemplateDialogFragment {
val frag = ChooseTemplateDialogFragment()
val args = Bundle()
args.putParcelable(ARG_PARENT_FOLDER, parentFolder)
args.putParcelable(ARG_CREATOR, creator)
args.putString(ARG_HEADLINE, headline)
frag.arguments = args
return frag
}
}
}

View file

@ -627,7 +627,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
}
@Override
public void showTemplate(Creator creator, String headline) {
public void showTemplate(@NonNull Creator creator, @NonNull String headline) {
ChooseTemplateDialogFragment.newInstance(mFile, creator, headline).show(requireActivity().getSupportFragmentManager(),
DIALOG_CREATE_DOCUMENT);
}