mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
This commit is contained in:
@@ -29,7 +29,7 @@ import com.itsaky.androidide.fragments.AppLogFragment;
|
||||
import com.itsaky.androidide.fragments.DiagnosticsListFragment;
|
||||
import com.itsaky.androidide.fragments.IDELogFragment;
|
||||
import com.itsaky.androidide.fragments.SearchResultFragment;
|
||||
import com.itsaky.androidide.fragments.SimpleOutputFragment;
|
||||
import com.itsaky.androidide.fragments.BuildOutputFragment;
|
||||
import com.itsaky.androidide.utils.ILogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -48,7 +48,7 @@ public class EditorBottomSheetTabAdapter extends FragmentStateAdapter {
|
||||
this.fragments.add(
|
||||
new Tab(
|
||||
fragmentActivity.getString(R.string.build_output),
|
||||
SimpleOutputFragment.class,
|
||||
BuildOutputFragment.class,
|
||||
++index));
|
||||
this.fragments.add(
|
||||
new Tab(fragmentActivity.getString(R.string.app_logs), AppLogFragment.class, ++index));
|
||||
@@ -117,8 +117,8 @@ public class EditorBottomSheetTabAdapter extends FragmentStateAdapter {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SimpleOutputFragment getBuildOutputFragment() {
|
||||
return findFragmentByClass(SimpleOutputFragment.class);
|
||||
public BuildOutputFragment getBuildOutputFragment() {
|
||||
return findFragmentByClass(BuildOutputFragment.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+6
-2
@@ -19,11 +19,13 @@ package com.itsaky.androidide.fragments
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.blankj.utilcode.util.ThreadUtils
|
||||
import com.itsaky.androidide.R
|
||||
|
||||
class SimpleOutputFragment : NonEditableEditorFragment() {
|
||||
class BuildOutputFragment : NonEditableEditorFragment() {
|
||||
private val unsavedLines: MutableList<String?> = ArrayList()
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
emptyStateViewModel.emptyMessage.value = getString(R.string.msg_emptyview_buildoutput)
|
||||
if (unsavedLines.isNotEmpty()) {
|
||||
for (line in unsavedLines) {
|
||||
editor?.append("${line!!.trim()}\n")
|
||||
@@ -48,7 +50,9 @@ class SimpleOutputFragment : NonEditableEditorFragment() {
|
||||
} else {
|
||||
"${output}\n"
|
||||
}
|
||||
editor!!.append(message)
|
||||
editor!!.append(message).also {
|
||||
emptyStateViewModel.isEmpty.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE 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.
|
||||
*
|
||||
* AndroidIDE 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 AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.fragments;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.itsaky.androidide.adapters.DiagnosticsAdapter;
|
||||
import com.itsaky.androidide.ui.EmptyView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DiagnosticsListFragment extends Fragment {
|
||||
|
||||
private RecyclerView list;
|
||||
private EmptyView emptyView;
|
||||
|
||||
private DiagnosticsAdapter unsavedAdapter;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup parent,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
final var container = new LinearLayout(inflater.getContext());
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
container.setLayoutParams(new ViewGroup.LayoutParams(-1, -1));
|
||||
|
||||
this.list = new RecyclerView(inflater.getContext());
|
||||
this.emptyView = new EmptyView(inflater.getContext());
|
||||
|
||||
container.addView(list, new LinearLayout.LayoutParams(-1, -1));
|
||||
container.addView(emptyView, new LinearLayout.LayoutParams(-1, -1));
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
list.setLayoutManager(new LinearLayoutManager(list.getContext()));
|
||||
list.setAdapter(
|
||||
unsavedAdapter != null ? unsavedAdapter : new DiagnosticsAdapter(new ArrayList<>(), null));
|
||||
unsavedAdapter = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
unsavedAdapter = null;
|
||||
list = null;
|
||||
emptyView = null;
|
||||
}
|
||||
|
||||
public void setAdapter(@NonNull DiagnosticsAdapter adapter) {
|
||||
if (list != null) {
|
||||
list.setAdapter(adapter);
|
||||
} else {
|
||||
unsavedAdapter = adapter;
|
||||
}
|
||||
}
|
||||
|
||||
public void handleResultVisibility(boolean error) {
|
||||
if (emptyView != null && list != null) {
|
||||
emptyView.setVisibility(error ? View.VISIBLE : View.GONE);
|
||||
list.setVisibility(error ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE 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.
|
||||
*
|
||||
* AndroidIDE 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 AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.itsaky.androidide.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.adapters.DiagnosticsAdapter
|
||||
|
||||
class DiagnosticsListFragment : RecyclerViewFragment<DiagnosticsAdapter>() {
|
||||
|
||||
override fun onCreateAdapter(): RecyclerView.Adapter<*> {
|
||||
return DiagnosticsAdapter(ArrayList(), null)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
emptyStateViewModel.emptyMessage.value = getString(R.string.msg_emptyview_diagnostics)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE 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.
|
||||
*
|
||||
* AndroidIDE 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 AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.itsaky.androidide.databinding.FragmentEmptyStateBinding
|
||||
import com.itsaky.androidide.viewmodel.EmptyStateFragmentViewModel
|
||||
|
||||
/**
|
||||
* A fragment that shows a message when there is no data to show in the subclass fragment.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
abstract class EmptyStateFragment<T : ViewBinding>(layout: Int,
|
||||
bind: (View) -> T) : FragmentWithBinding<T>(layout, bind) {
|
||||
|
||||
protected var emptyStateBinding: FragmentEmptyStateBinding? = null
|
||||
private set
|
||||
|
||||
protected val emptyStateViewModel by viewModels<EmptyStateFragmentViewModel>()
|
||||
|
||||
internal var isEmpty: Boolean
|
||||
get() = emptyStateViewModel.isEmpty.value ?: false
|
||||
set(value) {
|
||||
emptyStateViewModel.isEmpty.value = value
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View {
|
||||
|
||||
return FragmentEmptyStateBinding.inflate(inflater, container, false).also { emptyStateBinding ->
|
||||
this.emptyStateBinding = emptyStateBinding
|
||||
|
||||
// add the main fragment view
|
||||
emptyStateBinding.root.addView(
|
||||
super.onCreateView(inflater, emptyStateBinding.root, savedInstanceState)
|
||||
)
|
||||
}.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
emptyStateViewModel.isEmpty.observe(viewLifecycleOwner) { isEmpty ->
|
||||
emptyStateBinding?.apply {
|
||||
root.displayedChild = if (isEmpty) 0 else 1
|
||||
}
|
||||
}
|
||||
|
||||
emptyStateViewModel.emptyMessage.observe(viewLifecycleOwner) { message ->
|
||||
emptyStateBinding?.emptyView?.message = message
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
this.emptyStateBinding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
package com.itsaky.androidide.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
|
||||
/**
|
||||
@@ -43,6 +46,11 @@ class IDELogFragment : LogViewFragment() {
|
||||
override fun isSimpleFormattingEnabled() = true
|
||||
override fun getFilename() = "ide_logs"
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
emptyStateViewModel.emptyMessage.value = getString(R.string.msg_emptyview_idelogs)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
ILogger.removeLogListener(logListener)
|
||||
@@ -57,4 +65,9 @@ class IDELogFragment : LogViewFragment() {
|
||||
class AppLogFragment : LogViewFragment() {
|
||||
override fun isSimpleFormattingEnabled() = false
|
||||
override fun getFilename() = "app_logs"
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
emptyStateViewModel.emptyMessage.value = getString(R.string.msg_emptyview_applogs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,9 @@ package com.itsaky.androidide.fragments
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.blankj.utilcode.util.ThreadUtils
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.databinding.FragmentLogBinding
|
||||
import com.itsaky.androidide.editor.language.log.LogLanguage
|
||||
import com.itsaky.androidide.editor.schemes.IDEColorSchemeProvider
|
||||
@@ -44,7 +42,9 @@ import kotlin.math.min
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
abstract class LogViewFragment : Fragment(), ShareableOutputFragment {
|
||||
abstract class LogViewFragment :
|
||||
EmptyStateFragment<FragmentLogBinding>(R.layout.fragment_log, FragmentLogBinding::bind),
|
||||
ShareableOutputFragment {
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -78,8 +78,6 @@ abstract class LogViewFragment : Fragment(), ShareableOutputFragment {
|
||||
const val MAX_LINE_COUNT = TRIM_ON_LINE_COUNT - 300
|
||||
}
|
||||
|
||||
var binding: FragmentLogBinding? = null
|
||||
|
||||
private var lastLog = -1L
|
||||
|
||||
private val cacheLock = ReentrantLock()
|
||||
@@ -161,7 +159,13 @@ abstract class LogViewFragment : Fragment(), ShareableOutputFragment {
|
||||
}
|
||||
|
||||
private fun append(chars: CharSequence?) {
|
||||
chars?.let { ThreadUtils.runOnUiThread { binding?.editor?.append(chars) } }
|
||||
chars?.let {
|
||||
ThreadUtils.runOnUiThread {
|
||||
_binding?.editor?.append(chars)?.also {
|
||||
emptyStateViewModel.isEmpty.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun trimLinesAtStart() {
|
||||
@@ -171,7 +175,7 @@ abstract class LogViewFragment : Fragment(), ShareableOutputFragment {
|
||||
}
|
||||
|
||||
ThreadUtils.runOnUiThread {
|
||||
binding?.editor?.text?.apply {
|
||||
_binding?.editor?.text?.apply {
|
||||
if (lineCount <= TRIM_ON_LINE_COUNT) {
|
||||
isTrimming.set(false)
|
||||
return@apply
|
||||
@@ -193,18 +197,9 @@ abstract class LogViewFragment : Fragment(), ShareableOutputFragment {
|
||||
appendLog(line)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?,
|
||||
): View {
|
||||
binding = FragmentLogBinding.inflate(inflater, container, false)
|
||||
return binding!!.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val editor = this.binding!!.editor
|
||||
val editor = this.binding.editor
|
||||
editor.props.autoIndent = false
|
||||
editor.isEditable = false
|
||||
editor.dividerWidth = 0f
|
||||
@@ -246,24 +241,17 @@ abstract class LogViewFragment : Fragment(), ShareableOutputFragment {
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
binding?.editor?.release()
|
||||
_binding?.editor?.release()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
this.binding = null
|
||||
}
|
||||
|
||||
override fun getContent(): String {
|
||||
if (this.binding == null) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return this.binding!!.editor.text.toString()
|
||||
return this._binding?.editor?.text?.toString() ?: ""
|
||||
}
|
||||
|
||||
override fun clearOutput() {
|
||||
binding?.editor?.setText("")
|
||||
_binding?.editor?.setText("")?.also {
|
||||
emptyStateViewModel.isEmpty.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,40 +18,29 @@
|
||||
package com.itsaky.androidide.fragments;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.itsaky.androidide.R;
|
||||
import com.itsaky.androidide.databinding.FragmentNonEditableEditorBinding;
|
||||
import com.itsaky.androidide.editor.ui.IDEEditor;
|
||||
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE;
|
||||
import com.itsaky.androidide.utils.TypefaceUtilsKt;
|
||||
import com.itsaky.androidide.editor.ui.IDEEditor;
|
||||
|
||||
import io.github.rosemoe.sora.lang.EmptyLanguage;
|
||||
|
||||
public abstract class NonEditableEditorFragment extends Fragment
|
||||
public abstract class NonEditableEditorFragment extends
|
||||
EmptyStateFragment<FragmentNonEditableEditorBinding>
|
||||
implements ShareableOutputFragment {
|
||||
|
||||
private FragmentNonEditableEditorBinding binding;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
this.binding = FragmentNonEditableEditorBinding.inflate(inflater, container, false);
|
||||
return binding.getRoot();
|
||||
public NonEditableEditorFragment() {
|
||||
super(R.layout.fragment_non_editable_editor, FragmentNonEditableEditorBinding::bind);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
final var editor = binding.getRoot();
|
||||
getEmptyStateViewModel().getEmptyMessage().setValue(createEmptyStateMessage());
|
||||
final var editor = getBinding().getRoot();
|
||||
editor.setEditable(false);
|
||||
editor.setDividerWidth(0);
|
||||
editor.setEditorLanguage(new EmptyLanguage());
|
||||
@@ -63,10 +52,8 @@ public abstract class NonEditableEditorFragment extends Fragment
|
||||
editor.setColorScheme(SchemeAndroidIDE.newInstance(requireContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
private CharSequence createEmptyStateMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -82,6 +69,7 @@ public abstract class NonEditableEditorFragment extends Fragment
|
||||
|
||||
@Nullable
|
||||
public IDEEditor getEditor() {
|
||||
final var binding = get_binding();
|
||||
if (binding == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -103,5 +91,6 @@ public abstract class NonEditableEditorFragment extends Fragment
|
||||
|
||||
// Editing CodeEditor's content is a synchronized operation
|
||||
editor.getText().delete(0, editor.getText().length());
|
||||
getEmptyStateViewModel().isEmpty().setValue(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE 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.
|
||||
*
|
||||
* AndroidIDE 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 AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.databinding.FragmentRecyclerviewBinding
|
||||
|
||||
/**
|
||||
* A fragment which shows a [RecyclerView].
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
abstract class RecyclerViewFragment<A : RecyclerView.Adapter<*>> :
|
||||
EmptyStateFragment<FragmentRecyclerviewBinding>(R.layout.fragment_recyclerview,
|
||||
FragmentRecyclerviewBinding::bind) {
|
||||
|
||||
private var unsavedAdapter: A? = null
|
||||
|
||||
/**
|
||||
* Creates the adapter for the [RecyclerView].
|
||||
*/
|
||||
protected abstract fun onCreateAdapter(): RecyclerView.Adapter<*>
|
||||
|
||||
/**
|
||||
* Creates the layout manager for the [RecyclerView].
|
||||
*/
|
||||
protected open fun onCreateLayoutManager(): LayoutManager {
|
||||
return LinearLayoutManager(requireContext())
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding.root.apply {
|
||||
layoutManager = onCreateLayoutManager()
|
||||
adapter = unsavedAdapter ?: onCreateAdapter()
|
||||
}
|
||||
|
||||
unsavedAdapter = null
|
||||
|
||||
checkIsEmpty()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
unsavedAdapter = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the adapter for the [RecyclerView].
|
||||
*/
|
||||
fun setAdapter(adapter: A) {
|
||||
_binding?.root?.let { list -> list.adapter = adapter } ?: run { unsavedAdapter = adapter }
|
||||
checkIsEmpty()
|
||||
}
|
||||
|
||||
private fun checkIsEmpty() {
|
||||
if (_binding?.root?.adapter?.itemCount == 0) {
|
||||
emptyStateViewModel.isEmpty.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE 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.
|
||||
*
|
||||
* AndroidIDE 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 AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.fragments;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.itsaky.androidide.adapters.SearchListAdapter;
|
||||
import com.itsaky.androidide.ui.EmptyView;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
public class SearchResultFragment extends Fragment {
|
||||
|
||||
private RecyclerView list;
|
||||
private EmptyView emptyView;
|
||||
|
||||
private SearchListAdapter unsavedAdapter;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup parent,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
final var container = new LinearLayout(inflater.getContext());
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
container.setLayoutParams(new ViewGroup.LayoutParams(-1, -1));
|
||||
|
||||
this.list = new RecyclerView(inflater.getContext());
|
||||
this.emptyView = new EmptyView(inflater.getContext());
|
||||
|
||||
container.addView(list, new LinearLayout.LayoutParams(-1, -1));
|
||||
container.addView(emptyView, new LinearLayout.LayoutParams(-1, -1));
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
list.setLayoutManager(new LinearLayoutManager(list.getContext()));
|
||||
list.setAdapter(
|
||||
unsavedAdapter != null
|
||||
? unsavedAdapter
|
||||
: new SearchListAdapter(Collections.emptyMap(), this::noOp, this::noOp));
|
||||
unsavedAdapter = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
unsavedAdapter = null;
|
||||
list = null;
|
||||
emptyView = null;
|
||||
}
|
||||
|
||||
public void setAdapter(@NonNull final SearchListAdapter adapter) {
|
||||
if (list == null) {
|
||||
unsavedAdapter = adapter;
|
||||
return;
|
||||
}
|
||||
this.list.setAdapter(adapter);
|
||||
}
|
||||
|
||||
public void handleResultVisibility(boolean error) {
|
||||
if (emptyView != null && list != null) {
|
||||
emptyView.setVisibility(error ? View.VISIBLE : View.GONE);
|
||||
list.setVisibility(error ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private Unit noOp(Object obj) {
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE 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.
|
||||
*
|
||||
* AndroidIDE 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 AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.itsaky.androidide.fragments
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.itsaky.androidide.adapters.SearchListAdapter
|
||||
|
||||
class SearchResultFragment : RecyclerViewFragment<SearchListAdapter>() {
|
||||
|
||||
override fun onCreateAdapter(): RecyclerView.Adapter<*> {
|
||||
val noOp: (Any) -> Unit = {}
|
||||
return SearchListAdapter(emptyMap(), noOp, noOp)
|
||||
}
|
||||
}
|
||||
@@ -86,13 +86,15 @@ constructor(
|
||||
localContext.resources.getDimension(R.dimen.editor_sheet_collapsed_height)
|
||||
}
|
||||
|
||||
@JvmField var binding: LayoutEditorBottomSheetBinding
|
||||
@JvmField
|
||||
var binding: LayoutEditorBottomSheetBinding
|
||||
|
||||
val pagerAdapter: EditorBottomSheetTabAdapter
|
||||
|
||||
private val log = ILogger.newInstance("EditorBottomSheet")
|
||||
|
||||
companion object {
|
||||
|
||||
const val CHILD_SYMBOL_INPUT = 0
|
||||
const val CHILD_HEADER = 1
|
||||
const val CHILD_ACTION = 2
|
||||
@@ -138,7 +140,8 @@ constructor(
|
||||
val filename = fragment.getFilename()
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
val progress = android.app.ProgressDialog.show(context, null, context.getString(string.please_wait))
|
||||
val progress = android.app.ProgressDialog.show(context, null,
|
||||
context.getString(string.please_wait))
|
||||
executeAsync(fragment::getContent) {
|
||||
progress.dismiss()
|
||||
shareText(it, filename)
|
||||
@@ -234,11 +237,11 @@ constructor(
|
||||
}
|
||||
|
||||
fun handleDiagnosticsResultVisibility(errorVisible: Boolean) {
|
||||
runOnUiThread { pagerAdapter.diagnosticsFragment?.handleResultVisibility(errorVisible) }
|
||||
runOnUiThread { pagerAdapter.diagnosticsFragment?.isEmpty = errorVisible }
|
||||
}
|
||||
|
||||
fun handleSearchResultVisibility(errorVisible: Boolean) {
|
||||
runOnUiThread { pagerAdapter.searchResultFragment?.handleResultVisibility(errorVisible) }
|
||||
runOnUiThread { pagerAdapter.searchResultFragment?.isEmpty = errorVisible }
|
||||
}
|
||||
|
||||
fun setDiagnosticsAdapter(adapter: DiagnosticsAdapter) {
|
||||
@@ -300,7 +303,8 @@ constructor(
|
||||
flashError(context.getString(string.msg_output_text_extraction_failed))
|
||||
return
|
||||
}
|
||||
val pd = android.app.ProgressDialog.show(context, null, context.getString(string.please_wait), true, false)
|
||||
val pd = android.app.ProgressDialog.show(context, null, context.getString(string.please_wait),
|
||||
true, false)
|
||||
executeAsyncProvideError(
|
||||
Callable { writeTempFile(text, type) },
|
||||
CallbackWithError<File> { result: File?, error: Throwable? ->
|
||||
|
||||
@@ -21,16 +21,22 @@
|
||||
package com.itsaky.androidide.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import com.itsaky.androidide.R;
|
||||
import com.itsaky.androidide.utils.ResourceUtilsKt;
|
||||
|
||||
public class EmptyView extends RelativeLayout {
|
||||
|
||||
private static final int MESSAGE_TEXTVIEW = View.generateViewId();
|
||||
|
||||
private CharSequence message = null;
|
||||
|
||||
public EmptyView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@@ -54,7 +60,8 @@ public class EmptyView extends RelativeLayout {
|
||||
removeAllViews();
|
||||
|
||||
TextView text = new TextView(getContext());
|
||||
text.setText(com.itsaky.androidide.resources.R.string.msg_empty_view);
|
||||
text.setId(MESSAGE_TEXTVIEW);
|
||||
text.setText(getMessage());
|
||||
text.setTextColor(ResourceUtilsKt.resolveAttr(getContext(), R.attr.colorSecondaryVariant));
|
||||
text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
|
||||
|
||||
@@ -63,4 +70,18 @@ public class EmptyView extends RelativeLayout {
|
||||
|
||||
addView(text, params);
|
||||
}
|
||||
|
||||
public void setMessage(CharSequence message) {
|
||||
this.message = message;
|
||||
|
||||
final TextView text = findViewById(MESSAGE_TEXTVIEW);
|
||||
if (text != null) {
|
||||
text.setText(getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public CharSequence getMessage() {
|
||||
return TextUtils.isEmpty(message) ? getContext().getString(R.string.msg_empty_view) : message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE 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.
|
||||
*
|
||||
* AndroidIDE 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 AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.viewmodel
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.itsaky.androidide.R
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class EmptyStateFragmentViewModel : ViewModel() {
|
||||
|
||||
val isEmpty = MutableLiveData(true)
|
||||
val emptyMessage = MutableLiveData<CharSequence>("")
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ This file is part of AndroidIDE.
|
||||
~
|
||||
~ AndroidIDE 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.
|
||||
~
|
||||
~ AndroidIDE 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 AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<ViewFlipper xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.itsaky.androidide.ui.EmptyView
|
||||
android:id="@+id/empty_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</ViewFlipper>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ This file is part of AndroidIDE.
|
||||
~
|
||||
~ AndroidIDE 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.
|
||||
~
|
||||
~ AndroidIDE 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 AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
@@ -44,7 +44,11 @@ abstract class FragmentWithBinding<T : ViewBinding>(@LayoutRes layout: Int,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
return super.onCreateView(inflater, container, savedInstanceState)!!
|
||||
.also { _binding = bind(it) }
|
||||
.also(this::doBind)
|
||||
}
|
||||
|
||||
protected fun doBind(it: View) {
|
||||
_binding = bind(it)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<string name="ide_preferences">IDE preferences</string>
|
||||
<string name="discussions_on_telegram">Discussions on Telegram</string>
|
||||
<string name="official_tg_channel">Official Telegram Channel</string>
|
||||
<string name="msg_empty_view">I have nothing to show you…</string>
|
||||
<string name="msg_empty_view">No data</string>
|
||||
<string name="title_terminal">Terminal</string>
|
||||
<string name="reset">Reset</string>
|
||||
<string name="app_logs">App Logs</string>
|
||||
@@ -586,4 +586,8 @@
|
||||
<string name="idepref_group_debugging">Debugging</string>
|
||||
<string name="idepref_devOptions_dumpLogs_title">Dump logs</string>
|
||||
<string name="idepref_devOptions_dumpLogs_summary">Dump AndroidIDE logs to $HOME/.androidide/logs</string>
|
||||
<string name="msg_emptyview_applogs">Run the debug variant of your application to view its logs here.</string>
|
||||
<string name="msg_emptyview_idelogs">Logs from the IDE are shown here.</string>
|
||||
<string name="msg_emptyview_diagnostics">Open a file to show its diagnostic results</string>
|
||||
<string name="msg_emptyview_buildoutput">"Build the application or run a task to see its build output here. "</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user