mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
Use RecyclerView to show application and IDE logs
This commit is contained in:
Generated
+2
-54
@@ -140,65 +140,13 @@
|
||||
<entry key="..\:/Users/Akash Yadav/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_create_project_content.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Akash Yadav/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_widget_item.xml" value="0.264" />
|
||||
<entry key="..\:/Users/Akash Yadav/AndroidStudioProjects/android-ide/app/src/main/res/menu/menu_designer_widgets.xml" value="0.20854700854700856" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/activity_about.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/activity_crash_handler.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/activity_main.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/activity_preferences.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/activity_splash.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/fragment_log_view.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/fragment_main.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/fragment_non_editable_editor.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/fragment_wizard.xml" value="0.26046511627906976" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_about_items.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_add_attr_sheet.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_attr_editor_sheet.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_attr_editor_sheet_item.xml" value="0.25" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_attr_value_editor.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_banner.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_boolean_attr_editor.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_code_action_item.xml" value="0.5" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_code_editor.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_color_attr_editor.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_completion_item.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_crash_report.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_create_file_java.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_diagnostic_group.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_diagnostic_info.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_diagnostic_item.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_dialog_text_input.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_dimension_attr_editor.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_editor_actions.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_editor_bottom_sheet.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_editor_file_tree.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_editor_find_replace.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_filetree_item.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_loading_wizard.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_nav_header.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_optionssheet_item.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_popup_menu_item.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_progress_sheet.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_projects.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_projects_item.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_reference_attr_editor.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_search_project.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_search_result_group.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_search_result_item.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_sheet.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_simple_icon_text.xml" value="0.5" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_string_attr_editor.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_symbol_item.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_text_action_item.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_text_attr_editor.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/layout_text_size_slider.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/setup_footer.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/wizard_details.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/wizard_template_item.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/Users/Svetl/Documents/GitHub/AndroidIDE/app/src/main/res/layout/wizard_templates.xml" value="0.20416666666666666" />
|
||||
<entry key="..\:/itsaky/.gradle/caches/transforms-3/e4862cae80f8754ca1a451ad3e00b14c/transformed/jetified-editor-0.10.11/res/drawable/round_select_all_20.xml" value="0.1305" />
|
||||
<entry key="app/src/main/res/drawable/ic_gradle.xml" value="0.3265" />
|
||||
<entry key="app/src/main/res/drawable/ic_language_gradle.xml" value="0.3265" />
|
||||
<entry key="app/src/main/res/layout/activity_download.xml" value="0.35572916666666665" />
|
||||
<entry key="app/src/main/res/layout/fragment_log.xml" value="0.35572916666666665" />
|
||||
<entry key="app/src/main/res/layout/layout_dialog_text_input.xml" value="0.35572916666666665" />
|
||||
<entry key="app/src/main/res/layout/layout_log_line.xml" value="0.35572916666666665" />
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
|
||||
Binary file not shown.
@@ -84,7 +84,6 @@ import com.itsaky.androidide.databinding.ActivityEditorBinding;
|
||||
import com.itsaky.androidide.databinding.LayoutDiagnosticInfoBinding;
|
||||
import com.itsaky.androidide.databinding.LayoutSearchProjectBinding;
|
||||
import com.itsaky.androidide.fragments.FileTreeFragment;
|
||||
import com.itsaky.androidide.fragments.IDELogFragment;
|
||||
import com.itsaky.androidide.fragments.LogViewFragment;
|
||||
import com.itsaky.androidide.fragments.NonEditableEditorFragment;
|
||||
import com.itsaky.androidide.fragments.SearchResultFragment;
|
||||
@@ -1378,9 +1377,15 @@ public class EditorActivity extends StudioActivity
|
||||
editor.getEditor().setText("");
|
||||
}
|
||||
} else if (fragment instanceof LogViewFragment) {
|
||||
final var editor = (LogViewFragment) fragment;
|
||||
if (editor.getEditor() != null) {
|
||||
editor.getEditor().setText("");
|
||||
final LogViewFragment logFrag = (LogViewFragment) fragment;
|
||||
final var adapter = logFrag.getAdapter();
|
||||
if (adapter != null) {
|
||||
adapter.clear();
|
||||
} else {
|
||||
LOG.error(
|
||||
"Cannot clear contents. Adapter in LogViewFragment("
|
||||
+ logFrag.getLogType()
|
||||
+ ") is null.");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1390,22 +1395,40 @@ public class EditorActivity extends StudioActivity
|
||||
final var fragment =
|
||||
bottomSheetTabAdapter.getFragmentAtIndex(
|
||||
mBinding.bottomSheet.tabs.getSelectedTabPosition());
|
||||
CharSequence text = "";
|
||||
String type = "unknown_type";
|
||||
if (fragment instanceof SimpleOutputFragment) {
|
||||
var editor = (SimpleOutputFragment) fragment;
|
||||
text = editor.getEditor().getText();
|
||||
type = "build_output";
|
||||
} else if (fragment instanceof IDELogFragment) {
|
||||
var editor = (IDELogFragment) fragment;
|
||||
text = editor.getEditor().getText();
|
||||
type = "ide_logs";
|
||||
} else if (fragment instanceof LogViewFragment) {
|
||||
var editor = (IDELogFragment) fragment;
|
||||
text = editor.getEditor().getText();
|
||||
type = "app_logs";
|
||||
|
||||
if (fragment instanceof LogViewFragment) {
|
||||
final var logFrag = (LogViewFragment) fragment;
|
||||
final var type = logFrag.getLogType();
|
||||
final var adapter = logFrag.getAdapter();
|
||||
if (adapter != null) {
|
||||
|
||||
//noinspection deprecation
|
||||
final var progress =
|
||||
ProgressDialog.show(EditorActivity.this, null, getString(R.string.please_wait));
|
||||
CompletableFuture.runAsync(
|
||||
() -> {
|
||||
final var text = adapter.getAsString();
|
||||
ThreadUtils.runOnUiThread(
|
||||
() -> {
|
||||
progress.dismiss();
|
||||
shareText(text, type);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
LOG.error("Adapter in LogViewFragment(" + type + ") is null");
|
||||
}
|
||||
return;
|
||||
}
|
||||
shareText(text, type);
|
||||
|
||||
if (fragment instanceof SimpleOutputFragment) {
|
||||
final var editor = (SimpleOutputFragment) fragment;
|
||||
final var text = Objects.requireNonNull(editor.getEditor()).getText();
|
||||
final var type = "build_output";
|
||||
shareText(text, type);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.error("Unknown fragment:", fragment);
|
||||
});
|
||||
|
||||
if (!getApp().getPrefManager().getBoolean(KEY_BOTTOM_SHEET_SHOWN)
|
||||
|
||||
@@ -25,9 +25,9 @@ import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import com.itsaky.androidide.R;
|
||||
import com.itsaky.androidide.fragments.AppLogFragment;
|
||||
import com.itsaky.androidide.fragments.DiagnosticsListFragment;
|
||||
import com.itsaky.androidide.fragments.IDELogFragment;
|
||||
import com.itsaky.androidide.fragments.LogViewFragment;
|
||||
import com.itsaky.androidide.fragments.SearchResultFragment;
|
||||
import com.itsaky.androidide.fragments.SimpleOutputFragment;
|
||||
import com.itsaky.androidide.utils.ILogger;
|
||||
@@ -51,7 +51,7 @@ public class EditorBottomSheetTabAdapter extends FragmentStateAdapter {
|
||||
SimpleOutputFragment.class,
|
||||
++index));
|
||||
this.fragments.add(
|
||||
new Tab(fragmentActivity.getString(R.string.app_logs), LogViewFragment.class, ++index));
|
||||
new Tab(fragmentActivity.getString(R.string.app_logs), AppLogFragment.class, ++index));
|
||||
this.fragments.add(
|
||||
new Tab(fragmentActivity.getString(R.string.ide_logs), IDELogFragment.class, ++index));
|
||||
this.fragments.add(
|
||||
@@ -99,8 +99,8 @@ public class EditorBottomSheetTabAdapter extends FragmentStateAdapter {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LogViewFragment getLogFragment() {
|
||||
return findFragmentByClass(LogViewFragment.class);
|
||||
public AppLogFragment getLogFragment() {
|
||||
return findFragmentByClass(AppLogFragment.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.util.TypedValue
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.blankj.utilcode.util.SizeUtils
|
||||
import com.itsaky.androidide.adapters.LogLinesAdapter.VH
|
||||
import com.itsaky.androidide.models.LogLine
|
||||
import com.itsaky.androidide.utils.TypefaceUtils
|
||||
|
||||
/**
|
||||
* Adapter for the log view.
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class LogLinesAdapter(private val lines: MutableList<LogLine> = mutableListOf()) :
|
||||
RecyclerView.Adapter<VH>() {
|
||||
|
||||
var simpleFormatting = true
|
||||
|
||||
companion object {
|
||||
const val MAX_LINES = 10 * 1000
|
||||
}
|
||||
|
||||
class VH(val text: TextView) : RecyclerView.ViewHolder(text)
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun clear() {
|
||||
this.lines.clear()
|
||||
this.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun add(line: LogLine) {
|
||||
this.lines.add(line)
|
||||
this.notifyItemInserted(this.lines.lastIndex)
|
||||
|
||||
if (this.lines.size > MAX_LINES) {
|
||||
this.lines.removeAt(0)
|
||||
this.notifyItemRemoved(0)
|
||||
}
|
||||
}
|
||||
|
||||
fun getItem(index: Int) = this.lines[index]
|
||||
|
||||
fun getAsString() =
|
||||
StringBuilder()
|
||||
.apply {
|
||||
for (line in lines) {
|
||||
append(
|
||||
if (simpleFormatting) {
|
||||
line.toSimpleString()
|
||||
} else {
|
||||
line.toString()
|
||||
})
|
||||
append("\n")
|
||||
}
|
||||
}
|
||||
.toString()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
|
||||
val dp1 = SizeUtils.dp2px(1f)
|
||||
val text = TextView(parent.context)
|
||||
text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 11f)
|
||||
text.setPaddingRelative(dp1, dp1 / 2, dp1, dp1 / 2)
|
||||
text.setTextIsSelectable(true)
|
||||
text.typeface = TypefaceUtils.jetbrainsMono()
|
||||
return VH(text)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: VH, position: Int) {
|
||||
val line = getItem(position)
|
||||
val spanned =
|
||||
if (line is LogWrapper) {
|
||||
line.spanned!!
|
||||
} else {
|
||||
val spannable =
|
||||
SpannableString(
|
||||
if (simpleFormatting) line.toSimpleString() else line.toString())
|
||||
val color =
|
||||
when (line.priority) {
|
||||
LogLine.ERROR -> -0xbbcca
|
||||
LogLine.WARNING -> -0x14c5
|
||||
LogLine.INFO -> -0xb350b0
|
||||
else -> -0xa0a0b
|
||||
}
|
||||
spannable.setSpan(
|
||||
ForegroundColorSpan(color),
|
||||
0,
|
||||
spannable.length,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
lines[position] = LogWrapper(line).apply { spanned = spannable }
|
||||
spannable
|
||||
}
|
||||
holder.text.text = spanned
|
||||
}
|
||||
|
||||
override fun getItemCount() = this.lines.size
|
||||
|
||||
class LogWrapper(val log: LogLine) : LogLine() {
|
||||
|
||||
var spanned: Spannable? = null
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return this.log == other
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return this.log.hashCode()
|
||||
}
|
||||
|
||||
override fun toString() = this.log.toString()
|
||||
override fun toSimpleString(): String = this.log.toSimpleString()
|
||||
override fun formattedTagAndMessage(): String = this.log.formattedTagAndMessage()
|
||||
}
|
||||
}
|
||||
@@ -1,53 +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 androidx.annotation.NonNull;
|
||||
|
||||
import com.itsaky.androidide.models.LogLine;
|
||||
import com.itsaky.androidide.utils.ILogger;
|
||||
|
||||
public class IDELogFragment extends LogViewFragment {
|
||||
|
||||
private final ILogger.LogListener listener = this::log;
|
||||
|
||||
public IDELogFragment() {
|
||||
ILogger.addLogListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String onCreateLogString(@NonNull LogLine line) {
|
||||
return line.toSimpleString();
|
||||
}
|
||||
|
||||
private void log(int priority, String tag, @NonNull String message) {
|
||||
if (message.contains("\n")) {
|
||||
final var split = message.split("\n");
|
||||
for (var line : split) {
|
||||
logLine(priority, tag, line);
|
||||
}
|
||||
} else {
|
||||
logLine(priority, tag, message);
|
||||
}
|
||||
}
|
||||
|
||||
private void logLine(int priority, String tag, String message) {
|
||||
final var line = new LogLine(ILogger.priorityChar(priority), tag, message);
|
||||
appendLog(line);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 com.itsaky.androidide.utils.ILogger
|
||||
|
||||
/**
|
||||
* Fragment to show IDE logs.
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class IDELogFragment : LogViewFragment() {
|
||||
private var logListener: ILogger.LogListener? =
|
||||
ILogger.LogListener { priority, tag, message ->
|
||||
if (message.contains("\n")) {
|
||||
val split = message.split("\n").toTypedArray()
|
||||
for (line in split) {
|
||||
logLine(priority, tag, line)
|
||||
}
|
||||
} else {
|
||||
logLine(priority, tag, message)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
ILogger.addLogListener(this.logListener)
|
||||
}
|
||||
|
||||
override fun isSimpleFormattingEnabled() = true
|
||||
override fun getLogType() = "ide_logs"
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
ILogger.removeLogListener(logListener)
|
||||
logListener = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fragment to show application logs.
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class AppLogFragment : LogViewFragment() {
|
||||
override fun isSimpleFormattingEnabled() = false
|
||||
override fun getLogType() = "app_logs"
|
||||
}
|
||||
@@ -1,174 +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.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.blankj.utilcode.util.StringUtils;
|
||||
import com.blankj.utilcode.util.ThreadUtils;
|
||||
|
||||
import com.itsaky.androidide.R;
|
||||
import com.itsaky.androidide.databinding.FragmentLogViewBinding;
|
||||
import com.itsaky.androidide.language.logs.LogLanguageImpl;
|
||||
import com.itsaky.androidide.models.LogLine;
|
||||
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE;
|
||||
import com.itsaky.androidide.utils.TypefaceUtils;
|
||||
import com.itsaky.androidide.views.editor.IDEEditor;
|
||||
import com.itsaky.androidide.utils.SingleTextWatcher;
|
||||
import io.github.rosemoe.sora.lang.Language;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LogViewFragment extends Fragment {
|
||||
|
||||
private FragmentLogViewBinding binding;
|
||||
|
||||
private final Language language = getLanguage();
|
||||
private final List<LogLine> unsavedLines = new ArrayList<>();
|
||||
|
||||
private char priority;
|
||||
private String tag;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
binding = FragmentLogViewBinding.inflate(inflater, container, false);
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
final var editor = getEditor();
|
||||
editor.setEditable(false);
|
||||
editor.setDividerWidth(0);
|
||||
editor.setWordwrap(false);
|
||||
editor.setUndoEnabled(false);
|
||||
editor.setTypefaceLineNumber(TypefaceUtils.jetbrainsMono());
|
||||
editor.setTypefaceText(TypefaceUtils.jetbrainsMono());
|
||||
editor.setTextSize(12);
|
||||
editor.setColorScheme(new SchemeAndroidIDE());
|
||||
editor.setEditorLanguage(language);
|
||||
|
||||
final var arr = requireContext().getResources().getStringArray(R.array.logcat_units);
|
||||
binding.logPrioritySpinner.setAdapter(
|
||||
new ArrayAdapter<>(
|
||||
requireContext(),
|
||||
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
|
||||
arr));
|
||||
|
||||
binding.logPrioritySpinner.setOnItemSelectedListener(
|
||||
new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
priority = parent.getSelectedItem().toString().charAt(0);
|
||||
getEditor().setText("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {}
|
||||
});
|
||||
|
||||
binding
|
||||
.tagFilterInput
|
||||
.getEditText()
|
||||
.addTextChangedListener(
|
||||
new SingleTextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
tag = editable.toString();
|
||||
getEditor().setText("");
|
||||
}
|
||||
});
|
||||
|
||||
if (!unsavedLines.isEmpty()) {
|
||||
for (var line : unsavedLines) {
|
||||
getEditor().append(line.toString().trim() + "\n");
|
||||
applyToLanguage(line);
|
||||
}
|
||||
unsavedLines.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean filterLog(char priority, String tag, LogLine l) {
|
||||
return 'V' == priority
|
||||
|| (l.priorityChar == priority)
|
||||
&& (TextUtils.isEmpty(tag)
|
||||
|| (!TextUtils.isEmpty(tag) && (l.tag.toLowerCase().contains(tag.toLowerCase()))));
|
||||
}
|
||||
|
||||
private void applyToLanguage(LogLine line) {
|
||||
if (language instanceof LogLanguageImpl) {
|
||||
((LogLanguageImpl) this.language).addLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IDEEditor getEditor() {
|
||||
if (binding == null) {
|
||||
return null;
|
||||
}
|
||||
return binding.editor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
public void appendLog(LogLine line) {
|
||||
if (filterLog(priority, tag, line)) {
|
||||
if (getEditor() == null) {
|
||||
unsavedLines.add(line);
|
||||
return;
|
||||
}
|
||||
|
||||
final var lineString = onCreateLogString(line);
|
||||
final var msg = lineString.endsWith("\n") ? lineString : lineString + "\n";
|
||||
|
||||
ThreadUtils.runOnUiThread(() -> getEditor().append(msg));
|
||||
applyToLanguage(line);
|
||||
}
|
||||
}
|
||||
|
||||
protected String onCreateLogString(@NonNull LogLine line) {
|
||||
return line.toString();
|
||||
}
|
||||
|
||||
protected Language getLanguage() {
|
||||
return new LogLanguageImpl();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.itsaky.androidide.adapters.LogLinesAdapter
|
||||
import com.itsaky.androidide.databinding.FragmentLogBinding
|
||||
import com.itsaky.androidide.models.LogLine
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
|
||||
/**
|
||||
* Fragment to show logs in a [androidx.recyclerview.widget.RecyclerView].
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
abstract class LogViewFragment : Fragment() {
|
||||
|
||||
private val log = ILogger.newInstance(javaClass.simpleName)
|
||||
var binding: FragmentLogBinding? = null
|
||||
var adapter: LogLinesAdapter? = null
|
||||
|
||||
fun appendLog(line: LogLine) {
|
||||
if (this.binding == null || this.adapter == null) {
|
||||
return
|
||||
}
|
||||
|
||||
this.binding!!.lines.post {
|
||||
this.adapter!!.simpleFormatting = isSimpleFormattingEnabled()
|
||||
this.adapter!!.add(line)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun getLogType(): String
|
||||
|
||||
abstract fun isSimpleFormattingEnabled(): Boolean
|
||||
|
||||
protected open fun logLine(priority: Int, tag: String, message: String) {
|
||||
val line = LogLine(ILogger.priorityChar(priority), tag, message)
|
||||
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 manager = LinearLayoutManager(requireContext())
|
||||
this.binding!!.lines.layoutManager = manager
|
||||
|
||||
this.adapter = LogLinesAdapter()
|
||||
this.binding!!.lines.adapter = this.adapter
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
this.binding = null
|
||||
this.adapter = null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?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/>.
|
||||
-->
|
||||
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/lines"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
@@ -53,7 +53,7 @@ public class LogLine {
|
||||
|
||||
// For JSONRpc
|
||||
@SuppressWarnings("unused")
|
||||
private LogLine() {}
|
||||
protected LogLine() {}
|
||||
|
||||
public LogLine(char priorityChar, String tag, String message) {
|
||||
this("", "", "", "", priorityChar, tag, message);
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user