refactor: remove unused legacy project creator

This commit is contained in:
Akash Yadav
2023-06-20 21:06:27 +05:30
parent f61fc8e97d
commit 5a035da056
7 changed files with 2 additions and 1109 deletions
@@ -1,111 +0,0 @@
package com.itsaky.androidide.adapters;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.blankj.utilcode.util.ConvertUtils;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.shape.CornerFamily;
import com.itsaky.androidide.databinding.LayoutTemplateListItemBinding;
import com.itsaky.androidide.models.ProjectTemplate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class WizardTemplateAdapter extends RecyclerView.Adapter<WizardTemplateAdapter.ViewHolder> {
private final List<ProjectTemplate> mItems = new ArrayList<>();
private OnItemClickListener mListener;
public WizardTemplateAdapter() {
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public void submitList(@NonNull List<ProjectTemplate> newItems) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override
public int getOldListSize() {
return mItems.size();
}
@Override
public int getNewListSize() {
return newItems.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return Objects.equals(mItems.get(oldItemPosition), newItems.get(newItemPosition));
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return Objects.equals(mItems.get(oldItemPosition), newItems.get(newItemPosition));
}
});
mItems.clear();
mItems.addAll(newItems);
diffResult.dispatchUpdatesTo(this);
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutTemplateListItemBinding binding = LayoutTemplateListItemBinding.inflate(
LayoutInflater.from(parent.getContext()), parent, false);
ViewHolder holder = new ViewHolder(binding);
binding.getRoot().setOnClickListener(view1 -> {
if (mListener != null) {
int pos = holder.getBindingAdapterPosition();
if (pos != RecyclerView.NO_POSITION) {
mListener.onItemClick(mItems.get(pos), pos);
}
}
});
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.bind(mItems.get(position));
}
@Override
public int getItemCount() {
return mItems.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final ShapeableImageView icon;
public final TextView name;
public ViewHolder(LayoutTemplateListItemBinding view) {
super(view.getRoot());
icon = view.templateIcon;
name = view.templateName;
}
private void bind(ProjectTemplate template) {
name.setText(template.getName());
icon.setImageResource(template.getImageId());
icon.setShapeAppearanceModel(icon.getShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED, ConvertUtils.dp2px(8))
.build());
}
}
public interface OnItemClickListener {
void onItemClick(ProjectTemplate item, int position);
}
}
@@ -16,7 +16,6 @@ import com.itsaky.androidide.adapters.MainActionsListAdapter
import com.itsaky.androidide.app.BaseApplication
import com.itsaky.androidide.common.databinding.LayoutDialogProgressBinding
import com.itsaky.androidide.databinding.FragmentMainBinding
import com.itsaky.androidide.fragments.WizardFragment.OnProjectCreatedListener
import com.itsaky.androidide.models.MainScreenAction
import com.itsaky.androidide.preferences.databinding.LayoutDialogTextInputBinding
import com.itsaky.androidide.resources.R
@@ -32,7 +31,7 @@ import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.ProgressMonitor
import java.io.File
class MainFragment : BaseFragment(), OnProjectCreatedListener {
class MainFragment : BaseFragment() {
private val viewModel by viewModels<MainViewModel>(
ownerProducer = { requireActivity() })
@@ -86,7 +85,7 @@ class MainFragment : BaseFragment(), OnProjectCreatedListener {
viewModel.setScreen(MainViewModel.SCREEN_TEMPLATE_LIST)
}
override fun openProject(root: File) {
fun openProject(root: File) {
(requireActivity() as MainActivity).openProject(root)
}
@@ -1,533 +0,0 @@
package com.itsaky.androidide.fragments;
import static com.itsaky.androidide.resources.R.string;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.transition.TransitionManager;
import com.google.android.material.transition.MaterialFadeThrough;
import com.google.android.material.transition.MaterialSharedAxis;
import com.itsaky.androidide.adapters.WizardTemplateAdapter;
import com.itsaky.androidide.app.IDEApplication;
import com.itsaky.androidide.databinding.FragmentWizardBinding;
import com.itsaky.androidide.databinding.LayoutLoadingWizardBinding;
import com.itsaky.androidide.databinding.SetupFooterBinding;
import com.itsaky.androidide.databinding.WizardDetailsBinding;
import com.itsaky.androidide.databinding.WizardTemplatesBinding;
import com.itsaky.androidide.fragments.sheets.ProgressSheet;
import com.itsaky.androidide.managers.PreferenceManager;
import com.itsaky.androidide.models.ProjectTemplate;
import com.itsaky.androidide.utils.AndroidUtils;
import com.itsaky.androidide.utils.DialogUtils;
import com.itsaky.androidide.utils.Environment;
import com.itsaky.androidide.utils.FileUtil;
import com.itsaky.androidide.utils.FlashbarUtilsKt;
import com.itsaky.androidide.utils.SingleTextWatcher;
import com.itsaky.androidide.viewmodel.WizardViewModel;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
public class WizardFragment extends BaseFragment {
public static final String TAG = "WizardFragmentTag";
public static final String PREF_PACKAGE_DOMAIN_KEY = "pref_package_domain";
public static final String PREF_MIN_SDK_INDEX_KEY = "pref_min_sdk_index";
public static final String PREF_TERGET_SDK_INDEX_KEY = "pref_target_sdk_index";
public static final String PREF_SAVE_PROJECT_DIR_KEY = "pref_save_prohect_dir";
private FragmentWizardBinding binding;
private WizardTemplatesBinding templatesBinding;
private WizardDetailsBinding detailsBinding;
private WizardTemplateAdapter mAdapter;
private LayoutLoadingWizardBinding loadingLayout;
private SetupFooterBinding footerBinding;
private WizardViewModel mViewModel;
private ProgressSheet mProgressSheet;
private ProjectTemplate mCurrentTemplate;
private OnProjectCreatedListener mListener;
private boolean mLast;
private final OnBackPressedCallback onBackPressedCallback =
new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
onNavigateBack();
}
};
private int minSdkIndex;
private int targetSdkIndex;
@Nullable
@Override
public View onCreateView(
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentWizardBinding.inflate(inflater, container, false);
loadingLayout = binding.loadingLayout;
templatesBinding = binding.wizardTemplatesLayout;
detailsBinding = binding.wizardDetailsLayout;
footerBinding = binding.footerLayout;
mViewModel = new ViewModelProvider(this).get(WizardViewModel.class);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
requireActivity()
.getOnBackPressedDispatcher()
.addCallback(getViewLifecycleOwner(), onBackPressedCallback);
footerBinding.nextButton.setOnClickListener(v -> onNavigateNext());
footerBinding.exitButton.setOnClickListener(v -> onNavigateBack());
templatesBinding.templateRecyclerview.setLayoutManager(
new GridLayoutManager(requireContext(), 3));
mAdapter = new WizardTemplateAdapter();
templatesBinding.templateRecyclerview.setAdapter(mAdapter);
mViewModel.createTemplatesList();
mViewModel.getProjects().observe(getViewLifecycleOwner(), mAdapter::submitList);
mViewModel.getLoadingState().observe(getViewLifecycleOwner(), this::toggleLoadingState);
mViewModel
.getStatusMessage()
.observe(
getViewLifecycleOwner(),
(message) -> {
if (mProgressSheet == null) {
createProgressSheet();
}
setMessage(message);
});
mViewModel
.getErrorState()
.observe(
getViewLifecycleOwner(),
(message) -> {
if (mProgressSheet != null && mProgressSheet.isShowing()) {
mProgressSheet.dismiss();
}
FlashbarUtilsKt.flashError(message);
});
mViewModel
.getFileCreatedState()
.observe(
getViewLifecycleOwner(),
(file) -> {
if (file != null) onSuccess(file);
});
mAdapter.setOnItemClickListener(
(item, pos) -> {
mCurrentTemplate = item;
onNavigateNext();
});
initDetailsView();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mViewModel = null;
binding = null;
loadingLayout = null;
templatesBinding = null;
detailsBinding = null;
footerBinding = null;
mAdapter = null;
mProgressSheet = null;
}
@Override
public void onDestroy() {
super.onDestroy();
onBackPressedCallback.setEnabled(false);
}
public void onSuccess(File root) {
if (mProgressSheet != null && mProgressSheet.isShowing()) {
mProgressSheet.dismiss();
}
FlashbarUtilsKt.flashSuccess(string.project_created_successfully);
if (mListener != null) {
getParentFragmentManager().popBackStack();
mListener.openProject(root);
}
}
public void setOnProjectCreatedListener(OnProjectCreatedListener listener) {
mListener = listener;
}
private void toggleLoadingState(boolean loading) {
if (loading) {
showLoading();
} else {
showTemplatesView();
}
}
private String getSelectedItem(int pos, AutoCompleteTextView view) {
return view.getAdapter().getItem(pos).toString();
}
private void showLoading() {
TransitionManager.beginDelayedTransition((ViewGroup) requireView(), new MaterialFadeThrough());
binding.loadingLayout.getRoot().setVisibility(View.VISIBLE);
binding.wizardTemplatesLayout.getRoot().setVisibility(View.GONE);
footerBinding.nextButton.setVisibility(View.GONE);
}
private int getMinSdk() {
return getSdkVersion(detailsBinding.etMinSdk);
}
private int getTargetSdk() {
return getSdkVersion(detailsBinding.etTargetSdk);
}
private int getSdkVersion(AutoCompleteTextView view) {
try {
String sdk =
view.getText()
.toString()
.substring("API".length() + 1, "API".length() + 3); // at least 2 digits
return Integer.parseInt(sdk);
} catch (Exception e) {
FlashbarUtilsKt.flashError(e.getMessage());
}
return -1;
}
private boolean validateDetails() {
verifyAppName(detailsBinding.tilAppName.getEditText().getText(), false);
verifyPackageName(detailsBinding.tilPackageName.getEditText().getText());
if (detailsBinding.tilPackageName.isErrorEnabled()) {
return false;
}
if (detailsBinding.tilAppName.isErrorEnabled()) {
return false;
}
return mCurrentTemplate != null;
}
private void createNewProject() {
if (validateDetails()) {
final String appName =
Objects.requireNonNull(detailsBinding.etAppName).getText().toString().trim();
final String packageName =
Objects.requireNonNull(detailsBinding.etPackageName).getText().toString().trim();
final int minSdk = getMinSdk();
final int targetSdk = getTargetSdk();
final String savePath = detailsBinding.etSaveLocation.getText().toString().trim();
final String projectLanguage = detailsBinding.etLanguage.getText().toString();
final String cppToolChain =
getCppToolchans().get(detailsBinding.etToolchain.getText().toString());
PreferenceManager manager = IDEApplication.getInstance().getPrefManager();
manager.putInt(PREF_MIN_SDK_INDEX_KEY, minSdkIndex);
manager.putInt(PREF_TERGET_SDK_INDEX_KEY, targetSdkIndex);
manager.putString(PREF_PACKAGE_DOMAIN_KEY, AndroidUtils.getPackageDomain(packageName));
mViewModel.createProject(
mCurrentTemplate,
appName,
packageName,
minSdk,
targetSdk,
projectLanguage,
cppToolChain,
savePath);
}
}
private List<String> getSdks() {
return Arrays.asList(
"API 16: Android 4.0 (Ice Cream Sandwich)",
"API 17: Android 4.2 (JellyBean)",
"API 18: Android 4.3 (JellyBean)",
"API 19: Android 4.4 (KitKat)",
"API 20: Android 4.4W (KitKat Wear)",
"API 21: Android 5.0 (Lollipop)",
"API 22: Android 5.1 (Lollipop)",
"API 23: Android 6.0 (Marshmallow)",
"API 24: Android 7.0 (Nougat)",
"API 25: Android 7.1 (Nougat)",
"API 26: Android 8.0 (Oreo)",
"API 27: Android 8.1 (Oreo)",
"API 28: Android 9.0 (Pie)",
"API 29: Android 10.0 (Q)",
"API 30: Android 11.0 (R)",
"API 31: Android 12.0 (S)",
"API 32: Android 12.1L (S)",
"API 33: Android 13.0 (Tiramisu)");
}
private LinkedHashMap<String, String> getCppToolchans() {
LinkedHashMap<String, String> cppStandartType = new LinkedHashMap<>();
cppStandartType.put("Toolchain Default", "");
cppStandartType.put("C++11", "-std=c++11");
cppStandartType.put("C++14", "-std=c++14");
cppStandartType.put("C++17", "-std=c++17");
return cppStandartType;
}
private void onNavigateBack() {
if (!mLast) {
getParentFragmentManager().popBackStack();
} else {
showTemplatesView();
mLast = false;
}
}
private void onNavigateNext() {
if (!mLast) {
showDetailsView();
mLast = true;
} else {
createNewProject();
}
}
private void showTemplatesView() {
MaterialSharedAxis sharedAxis = new MaterialSharedAxis(MaterialSharedAxis.X, false);
TransitionManager.beginDelayedTransition((ViewGroup) requireView(), sharedAxis);
binding.loadingLayout.getRoot().setVisibility(View.GONE);
templatesBinding.getRoot().setVisibility(View.GONE);
detailsBinding.getRoot().setVisibility(View.GONE);
templatesBinding.getRoot().setVisibility(View.VISIBLE);
detailsBinding.tilToolchain.setVisibility(View.GONE);
footerBinding.nextButton.setVisibility(View.GONE);
footerBinding.nextButton.setText(string.next);
footerBinding.exitButton.setText(string.exit);
binding.wizardDescriptionId.setText(string.new_project);
}
private void showDetailsView() {
PreferenceManager manager = IDEApplication.getInstance().getPrefManager();
List<String> languages = new ArrayList<>();
if (mCurrentTemplate != null) {
if (mCurrentTemplate.isSupportJava()) {
languages.add("Java");
}
if (mCurrentTemplate.isSupportKotlin()) {
languages.add("Kotlin");
}
}
final var packageName =
manager.getString(PREF_PACKAGE_DOMAIN_KEY, "com.example").concat(".myapplication");
detailsBinding.etAppName.setText(string.template_def_app_name);
detailsBinding.etPackageName.setText(packageName);
detailsBinding.tilLanguage.setEnabled(languages.size() != 1);
detailsBinding.etLanguage.setAdapter(
new ArrayAdapter<>(
requireContext(),
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
languages));
detailsBinding.etLanguage.setListSelection(0);
if (mCurrentTemplate.isCpp()) {
detailsBinding.tilToolchain.setVisibility(View.VISIBLE);
detailsBinding.etToolchain.setAdapter(
new ArrayAdapter<>(
requireContext(),
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
getCppToolchans().keySet().toArray(new String[0])));
detailsBinding.etToolchain.setListSelection(0);
detailsBinding.etToolchain.setText(getSelectedItem(0, detailsBinding.etToolchain), false);
showDialogNdkNotSupportedOfficially();
}
detailsBinding.etLanguage.setText(getSelectedItem(0, detailsBinding.etLanguage), false);
minSdkIndex = manager.getInt(PREF_MIN_SDK_INDEX_KEY, 5);
// google recommended use latest target sdk version
targetSdkIndex = manager.getInt(PREF_TERGET_SDK_INDEX_KEY, getSdks().size() - 1);
detailsBinding.etMinSdk.setListSelection(minSdkIndex);
detailsBinding.etMinSdk.setText(getSelectedItem(minSdkIndex, detailsBinding.etMinSdk), false);
detailsBinding.etTargetSdk.setListSelection(targetSdkIndex);
detailsBinding.etTargetSdk.setText(
getSelectedItem(targetSdkIndex, detailsBinding.etTargetSdk), false);
setSaveLocation();
loadingLayout.getRoot().setVisibility(View.GONE);
detailsBinding.getRoot().setVisibility(View.GONE);
MaterialSharedAxis sharedAxis = new MaterialSharedAxis(MaterialSharedAxis.X, true);
TransitionManager.beginDelayedTransition((ViewGroup) requireView(), sharedAxis);
detailsBinding.getRoot().setVisibility(View.VISIBLE);
templatesBinding.getRoot().setVisibility(View.GONE);
binding.wizardDescriptionId.setText(mCurrentTemplate.getName());
footerBinding.nextButton.setText(string.create_project);
footerBinding.nextButton.setVisibility(View.VISIBLE);
footerBinding.exitButton.setText(string.previous);
}
private void initDetailsView() {
PreferenceManager manager = IDEApplication.getInstance().getPrefManager();
detailsBinding
.tilAppName
.getEditText()
.addTextChangedListener(
new SingleTextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
verifyAppName(editable, true);
}
});
detailsBinding
.tilPackageName
.getEditText()
.addTextChangedListener(
new SingleTextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
verifyPackageName(editable);
}
});
detailsBinding.etMinSdk.setAdapter(
new ArrayAdapter<>(
requireContext(),
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
getSdks()));
detailsBinding.etMinSdk.setOnItemClickListener(
(parent, view, position, id) -> minSdkIndex = position);
detailsBinding.etTargetSdk.setAdapter(
new ArrayAdapter<>(
requireContext(),
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
getSdks()));
detailsBinding.etTargetSdk.setOnItemClickListener(
(parent, view, position, id) -> targetSdkIndex = position);
detailsBinding.tilSaveLocation.setEndIconOnClickListener(
v -> {
pickDirectory(
p -> {
manager.putString(PREF_SAVE_PROJECT_DIR_KEY, p.getAbsolutePath());
Environment.setProjectDir(p);
setSaveLocation();
});
});
}
private void setPackageName(String appName) {
final String packageName =
Objects.requireNonNull(detailsBinding.etPackageName).getText().toString().trim();
String newPackageName = AndroidUtils.appNameToPackageName(appName, packageName);
detailsBinding.etPackageName.setText(newPackageName);
}
private void setSaveLocation() {
PreferenceManager manager = IDEApplication.getInstance().getPrefManager();
String saveProjectPath =
manager.getString(PREF_SAVE_PROJECT_DIR_KEY, Environment.PROJECTS_DIR.getAbsolutePath())
+ File.separator
+ AndroidUtils.trimWhiteSpace(detailsBinding.etAppName.getText().toString().trim());
String newPath = FileUtil.getTargetNonExistPath(saveProjectPath, true);
detailsBinding.etSaveLocation.setText(newPath);
}
private void verifyPackageName(Editable editable) {
String packageName = editable.toString();
String pkgCheckerMsg = AndroidUtils.validatePackageName(packageName);
if (!TextUtils.isEmpty(pkgCheckerMsg)) {
detailsBinding.tilPackageName.setError(pkgCheckerMsg);
} else {
detailsBinding.tilPackageName.setErrorEnabled(false);
}
}
private void verifyAppName(Editable editable, boolean isAddToPackage) {
String name = editable.toString().trim();
if (TextUtils.isEmpty(name)) {
detailsBinding.tilAppName.setError(getString(string.wizard_error_name_empty));
return;
} else if (!AndroidUtils.validateNameChecker(AndroidUtils.trimWhiteSpace(name))) {
detailsBinding.tilAppName.setError(getString(string.wizard_error_name_illegal));
return;
} else {
detailsBinding.tilAppName.setErrorEnabled(false);
}
if (isAddToPackage) {
setPackageName(name);
}
setSaveLocation();
}
private void createProgressSheet() {
mProgressSheet = new ProgressSheet();
}
private void setMessage(String msg) {
if (mProgressSheet == null) {
createProgressSheet();
}
mProgressSheet.setMessage(msg);
}
private void showDialogNdkNotSupportedOfficially() {
DialogUtils.newMaterialDialogBuilder(requireContext())
.setPositiveButton(android.R.string.ok, null)
.setTitle(string.title_warning)
.setMessage(string.msg_ndk_currently_unsupported)
.setCancelable(false)
.create()
.show();
}
public interface OnProjectCreatedListener {
void openProject(File project);
}
}
@@ -1,217 +0,0 @@
package com.itsaky.androidide.viewmodel;
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.blankj.utilcode.util.CollectionUtils;
import com.itsaky.androidide.interfaces.ProjectWriterCallback;
import com.itsaky.androidide.models.NewProjectDetails;
import com.itsaky.androidide.models.ProjectTemplate;
import com.itsaky.androidide.resources.R;
import com.itsaky.androidide.tasks.TaskExecutor;
import com.itsaky.androidide.tasks.callables.ProjectCreatorCallable;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class WizardViewModel extends AndroidViewModel {
private final MutableLiveData<List<ProjectTemplate>> mProjectTemplatesList =
new MutableLiveData<>(CollectionUtils.newArrayList());
private final MutableLiveData<Boolean> mLoadingState = new MutableLiveData<>(true);
private final MutableLiveData<String> mErrorMessageState = new MutableLiveData<>();
private final MutableLiveData<String> mMessageState = new MutableLiveData<>();
private final MutableLiveData<File> mCreatedProject = new MutableLiveData<>(null);
public WizardViewModel(@NonNull Application application) {
super(application);
}
public void createTemplatesList() {
TaskExecutor.executeAsync(this::createTemplates);
}
private Void createTemplates() {
List<ProjectTemplate> mTemplates = new ArrayList<>();
ProjectTemplate
empty =
new ProjectTemplate()
.setId(0)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(getApplication().getApplicationContext(), R.string.template_empty)
.setDescription(
getApplication().getApplicationContext(), R.string.template_description_empty)
.setImageId(R.drawable.template_empty_activity),
basic =
new ProjectTemplate()
.setId(1)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(getApplication().getApplicationContext(), R.string.template_basic)
.setDescription(
getApplication().getApplicationContext(), R.string.template_description_basic)
.setImageId(R.drawable.template_basic_activity),
drawer =
new ProjectTemplate()
.setId(2)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(), R.string.template_navigation_drawer)
.setDescription(
getApplication().getApplicationContext(),
R.string.template_description_navigation_drawer)
.setImageId(R.drawable.template_blank_activity_drawer),
bottomTabs =
new ProjectTemplate()
.setId(3)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(), R.string.template_navigation_tabs)
.setImageId(R.drawable.template_bottom_navigation_activity),
tabs =
new ProjectTemplate()
.setId(4)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(getApplication().getApplicationContext(), R.string.template_tabs)
.setImageId(R.drawable.template_blank_activity_tabs),
fragmentViewModel =
new ProjectTemplate()
.setId(5)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(
getApplication().getApplicationContext(),
R.string.template_fragment_and_viewmodel)
.setImageId(R.drawable.template_empty_activity),
cppWizard =
new ProjectTemplate()
.setId(6)
.setSupportJava(true)
.setSupportKotlin(true)
.setIsCpp(true)
.setName(getApplication().getApplicationContext(), R.string.template_cpp)
.setImageId(R.drawable.template_cpp_configure),
compose =
new ProjectTemplate()
.setId(7)
.setSupportKotlin(true)
.setName(getApplication().getApplicationContext(), R.string.template_compose)
.setDescription(
getApplication().getApplicationContext(), R.string.template_description_compose)
.setImageId(R.drawable.template_compose_empty_activity),
libgdx =
new ProjectTemplate()
.setId(8)
.setSupportJava(true)
.setName(getApplication().getApplicationContext(), R.string.template_libgdx)
.setDescription(
getApplication().getApplicationContext(), R.string.template_description_libgdx)
.setImageId(R.drawable.template_game_activity),
noActivity =
new ProjectTemplate()
.setId(9)
.setSupportJava(true)
.setSupportKotlin(true)
.setName(getApplication().getApplicationContext(), R.string.template_no_activity)
.setDescription(
getApplication().getApplicationContext(), R.string.template_no_activity_description)
.setImageId(R.drawable.template_no_activity),
NoAndroidX =
new ProjectTemplate()
.setId(10)
.setSupportJava(true)
.setSupportKotlin(false)
.setName(getApplication().getApplicationContext(), R.string.template_no_AndroidX)
.setDescription(
getApplication().getApplicationContext(), R.string.template_description_noAndroidX)
.setImageId(R.drawable.template_empty_noandroidx);
mTemplates.add(noActivity);
mTemplates.add(empty);
mTemplates.add(basic);
mTemplates.add(drawer);
mTemplates.add(bottomTabs);
mTemplates.add(tabs);
mTemplates.add(fragmentViewModel);
mTemplates.add(cppWizard);
mTemplates.add(compose);
mTemplates.add(libgdx);
mTemplates.add(NoAndroidX);
mProjectTemplatesList.postValue(mTemplates);
mLoadingState.postValue(false);
return null;
}
public LiveData<List<ProjectTemplate>> getProjects() {
return mProjectTemplatesList;
}
public LiveData<Boolean> getLoadingState() {
return mLoadingState;
}
public LiveData<String> getErrorState() {
return mErrorMessageState;
}
public LiveData<File> getFileCreatedState() {
return mCreatedProject;
}
public LiveData<String> getStatusMessage() {
return mMessageState;
}
public void createProject(
ProjectTemplate currentTemplate,
String appName,
String packageName,
int minSdk,
int targetSdk,
String language,
String cppFlags,
String savePath) {
final var details =
new NewProjectDetails(
appName, packageName, minSdk, targetSdk, language, cppFlags, savePath);
final var callable = new ProjectCreatorCallable(currentTemplate, details, createCallback());
TaskExecutor.executeAsync(callable);
}
private ProjectWriterCallback createCallback() {
return new ProjectWriterCallback() {
@Override
public void beforeBegin() {
mMessageState.setValue(getApplication().getString(R.string.msg_begin_project_write));
}
@Override
public void onProcessTask(String taskName) {
mMessageState.setValue(taskName);
}
@Override
public void onSuccess(File rootDir) {
mCreatedProject.setValue(rootDir);
}
@Override
public void onFailed(String reason) {
mErrorMessageState.setValue(reason);
}
};
}
}
@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp"
tools:ignore="Overdraw">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<TextView
android:id="@+id/wizard_description_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
android:paddingTop="16dp"
android:paddingBottom="2dp"
android:text="@string/new_project"
android:textSize="24sp"
android:textStyle="bold" />
<include
android:id="@+id/wizard_templates_layout"
layout="@layout/wizard_templates"
android:visibility="visible" />
<include
android:id="@+id/wizard_details_layout"
layout="@layout/wizard_details"
android:visibility="gone" />
<include
android:id="@+id/loading_layout"
layout="@layout/layout_loading_wizard"
android:visibility="gone" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<include
android:id="@+id/footer_layout"
layout="@layout/setup_footer" />
</LinearLayout>
-166
View File
@@ -1,166 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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="match_parent"
android:paddingTop="8dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_app_name"
style="@style/Widget.Material3.TextInputEditText.OutlinedBox.Dense"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/project_app_name"
app:counterEnabled="true"
app:counterMaxLength="20"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:placeholderText="My Application"
app:startIconDrawable="@drawable/ic_android">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_app_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:inputType="textNoSuggestions"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_package_name"
style="@style/Widget.Material3.TextInputEditText.OutlinedBox.Dense"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/package_name"
app:counterEnabled="true"
app:counterMaxLength="40"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_app_name"
app:placeholderText="com.example.myapplication"
app:startIconDrawable="@drawable/ic_package">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_package_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:inputType="textNoSuggestions"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_save_location"
style="@style/Widget.Material3.TextInputEditText.OutlinedBox.Dense"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/wizard_save_location"
app:endIconDrawable="@drawable/ic_folder"
app:endIconMode="custom"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_package_name"
app:placeholderText="/storage/emulated/0/AppProjects/MyApplication">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_save_location"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="start"
android:inputType="textNoSuggestions" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_language"
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="@string/wizard_language"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_save_location">
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="@+id/et_language"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_toolchain"
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="@string/wizard_toolchain"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_language">
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="@+id/et_toolchain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_min_sdk"
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="@string/minimum_sdk"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_toolchain"
app:startIconDrawable="@drawable/ic_min_sdk">
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="@+id/et_min_sdk"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_target_sdk"
style="@style/Widget.Material3.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="@string/target_sdk"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_min_sdk"
app:startIconDrawable="@drawable/ic_target_sdk">
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="@+id/et_target_sdk"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/template_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
tools:itemCount="10"
tools:listitem="@layout/layout_template_list_item"
tools:spanCount="3" />
</FrameLayout>