Skip to content

Commit 68c6951

Browse files
committed
feat(download): 添加模组/整合包翻译查询功能
- 新增 TranslationDialog 对话框用于显示模组名称翻译 - 在下载页面添加翻译图标按钮,仅在中文环境下显示 - 实现模组名称搜索功能,支持实时过滤翻译结果 - 集成 ModTranslations 模块提供翻译数据支持 - 添加 RecyclerView 展示翻译结果列表 - 实现点击翻译项自动填充到搜索框功能 - 添加 ic_translation 图标资源文件 - 创建 dialog_translation 和 item_translation 布局文件
1 parent 60300e4 commit 68c6951

File tree

8 files changed

+232
-2
lines changed

8 files changed

+232
-2
lines changed

FCL/src/main/java/com/tungsten/fcl/ui/download/DownloadPage.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@
7070
import java.util.concurrent.CancellationException;
7171
import java.util.stream.Collectors;
7272

73+
import kotlin.Unit;
74+
import kotlin.jvm.functions.Function1;
75+
7376
public class DownloadPage extends FCLCommonPage implements ManageUI.VersionLoadable, View.OnClickListener {
7477

7578
protected RemoteModRepository repository;
@@ -437,4 +440,12 @@ private void refreshCategory(boolean search) {
437440
if (search) search();
438441
}).start();
439442
}
443+
444+
void showTranslationDialog() {
445+
new TranslationDialog(getContext(), repository, s -> {
446+
nameEditText.setText(s);
447+
search();
448+
return null;
449+
}).show();
450+
}
440451
}

FCL/src/main/java/com/tungsten/fcl/ui/download/ModDownloadPage.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
import com.tungsten.fclcore.mod.RemoteModRepository;
1616
import com.tungsten.fclcore.mod.curse.CurseForgeRemoteModRepository;
1717
import com.tungsten.fclcore.mod.modrinth.ModrinthRemoteModRepository;
18+
import com.tungsten.fcllibrary.component.view.FCLImageView;
1819
import com.tungsten.fcllibrary.component.view.FCLUILayout;
20+
import com.tungsten.fcllibrary.util.LocaleUtils;
1921

2022
import java.util.ArrayList;
2123
import java.util.List;
@@ -35,6 +37,18 @@ public ModDownloadPage(Context context, int id, FCLUILayout parent, int resId) {
3537
create();
3638
}
3739

40+
@Override
41+
public void onCreate() {
42+
super.onCreate();
43+
if (LocaleUtils.isChinese(getContext())) {
44+
FCLImageView translate = findViewById(R.id.translate);
45+
translate.setVisibility(View.VISIBLE);
46+
translate.setOnClickListener(v -> {
47+
showTranslationDialog();
48+
});
49+
}
50+
}
51+
3852
@Override
3953
public void create() {
4054
super.create();

FCL/src/main/java/com/tungsten/fcl/ui/download/ModpackDownloadPage.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111
import com.tungsten.fclcore.mod.curse.CurseForgeRemoteModRepository;
1212
import com.tungsten.fclcore.mod.modrinth.ModrinthRemoteModRepository;
1313
import com.tungsten.fcllibrary.component.view.FCLButton;
14+
import com.tungsten.fcllibrary.component.view.FCLImageView;
1415
import com.tungsten.fcllibrary.component.view.FCLUILayout;
16+
import com.tungsten.fcllibrary.util.LocaleUtils;
1517

1618
public class ModpackDownloadPage extends DownloadPage {
1719

1820
private FCLButton installModpack;
21+
private FCLImageView translate;
1922

2023
public ModpackDownloadPage(Context context, int id, FCLUILayout parent, int resId) {
2124
super(context, id, parent, resId, null);
@@ -73,8 +76,15 @@ protected String getLocalizedOfficialPage() {
7376
public void onCreate() {
7477
super.onCreate();
7578
installModpack = findViewById(R.id.install_modpack);
79+
translate = findViewById(R.id.translate);
7680
installModpack.setVisibility(View.VISIBLE);
81+
if (LocaleUtils.isChinese(getContext())) {
82+
translate.setVisibility(View.VISIBLE);
83+
} else {
84+
translate.setVisibility(View.GONE);
85+
}
7786
installModpack.setOnClickListener(this);
87+
translate.setOnClickListener(this);
7888
}
7989

8090
@Override
@@ -83,5 +93,8 @@ public void onClick(View v) {
8393
if (v == installModpack) {
8494
Versions.importModpack(getContext(), getParent());
8595
}
96+
if (v == translate) {
97+
showTranslationDialog();
98+
}
8699
}
87100
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package com.tungsten.fcl.ui.download
2+
3+
import android.annotation.SuppressLint
4+
import android.content.Context
5+
import android.text.Editable
6+
import android.text.TextWatcher
7+
import android.view.LayoutInflater
8+
import android.view.View
9+
import android.view.ViewGroup
10+
import androidx.core.util.Function
11+
import androidx.lifecycle.lifecycleScope
12+
import androidx.recyclerview.widget.LinearLayoutManager
13+
import androidx.recyclerview.widget.RecyclerView
14+
import com.tungsten.fcl.R
15+
import com.tungsten.fcl.databinding.DialogTranslationBinding
16+
import com.tungsten.fcl.databinding.ItemTranslationBinding
17+
import com.tungsten.fcl.util.ModTranslations
18+
import com.tungsten.fclcore.mod.RemoteModRepository
19+
import com.tungsten.fcllibrary.component.dialog.FCLDialog
20+
import com.tungsten.fcllibrary.component.view.FCLEditText
21+
import com.tungsten.fcllibrary.util.ConvertUtils
22+
import kotlinx.coroutines.Dispatchers
23+
import kotlinx.coroutines.launch
24+
import kotlinx.coroutines.withContext
25+
26+
class TranslationDialog(
27+
context: Context,
28+
repository: RemoteModRepository,
29+
callback: (String) -> Unit
30+
) : FCLDialog(context) {
31+
private var text: FCLEditText
32+
private var recyclerView: RecyclerView
33+
private var adapter: TranslationAdapter
34+
35+
init {
36+
window?.setLayout(ConvertUtils.dip2px(context, 500f), ViewGroup.LayoutParams.MATCH_PARENT)
37+
val binding = DialogTranslationBinding.inflate(LayoutInflater.from(context))
38+
setContentView(binding.root)
39+
text = binding.text
40+
recyclerView = binding.recyclerView
41+
recyclerView.layoutManager = LinearLayoutManager(context)
42+
val newCallback: (String) -> Unit = {
43+
dismiss()
44+
callback(it)
45+
}
46+
adapter = TranslationAdapter(context, mutableListOf(), newCallback)
47+
recyclerView.adapter = adapter
48+
binding.cancel.setOnClickListener { dismiss() }
49+
text.addTextChangedListener(object : TextWatcher {
50+
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
51+
override fun onTextChanged(
52+
s: CharSequence?,
53+
start: Int,
54+
before: Int,
55+
count: Int
56+
) {
57+
}
58+
59+
override fun afterTextChanged(s: Editable?) {
60+
lifecycleScope.launch(Dispatchers.Default) {
61+
val s = text.text?.toString() ?: return@launch
62+
val mods = ModTranslations.getTranslationsByRepositoryType(repository.type)
63+
.searchMod(s)
64+
withContext(Dispatchers.Main) {
65+
adapter.update(mods)
66+
}
67+
}
68+
}
69+
})
70+
}
71+
72+
inner class TranslationAdapter(
73+
val context: Context,
74+
private val translationList: MutableList<ModTranslations.Mod>,
75+
val callback: (String) -> Unit
76+
) :
77+
RecyclerView.Adapter<TranslationAdapter.TranslationViewHolder>() {
78+
79+
inner class TranslationViewHolder(view: View) :
80+
RecyclerView.ViewHolder(view)
81+
82+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TranslationViewHolder {
83+
return TranslationViewHolder(
84+
LayoutInflater.from(context).inflate(R.layout.item_translation, parent, false)
85+
)
86+
}
87+
88+
override fun getItemCount(): Int {
89+
return translationList.size
90+
}
91+
92+
@SuppressLint("SetTextI18n")
93+
override fun onBindViewHolder(holder: TranslationViewHolder, position: Int) {
94+
val binding = ItemTranslationBinding.bind(holder.itemView)
95+
val mod = translationList[position]
96+
binding.text.text = "${mod.name} ${mod.subname} ${mod.abbr}"
97+
binding.root.setOnClickListener {
98+
callback(mod.subname.ifEmpty { mod.abbr })
99+
}
100+
}
101+
102+
@SuppressLint("NotifyDataSetChanged")
103+
fun update(translationList: List<ModTranslations.Mod>) {
104+
this.translationList.clear()
105+
this.translationList.addAll(translationList)
106+
notifyDataSetChanged()
107+
}
108+
}
109+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="40dp"
3+
android:height="40dp"
4+
android:viewportWidth="1024"
5+
android:viewportHeight="1024">
6+
<path
7+
android:fillColor="#FF000000"
8+
android:pathData="M213.3,640v85.3a85.3,85.3 0,0 0,78.9 85.1L298.7,810.7h128v85.3L298.7,896a170.7,170.7 0,0 1,-170.7 -170.7v-85.3h85.3zM768,426.7l187.7,469.3h-91.9l-51.2,-128h-174.5l-51.2,128h-91.9L682.7,426.7h85.3zM725.3,549.8L672.1,682.7h106.3L725.3,549.8zM341.3,85.3v85.3h170.7v298.7L341.3,469.3v128L256,597.3v-128L85.3,469.3L85.3,170.7h170.7L256,85.3h85.3zM725.3,128a170.7,170.7 0,0 1,170.7 170.7v85.3h-85.3L810.7,298.7a85.3,85.3 0,0 0,-85.3 -85.3h-128L597.3,128h128zM256,256L170.7,256v128h85.3L256,256zM426.7,256L341.3,256v128h85.3L426.7,256z"/>
9+
</vector>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:layout_width="match_parent"
6+
android:layout_height="match_parent"
7+
android:padding="10dp">
8+
9+
<TextView
10+
android:id="@+id/title"
11+
android:layout_width="wrap_content"
12+
android:layout_height="wrap_content"
13+
android:text="模组/整合包对应英文查询"
14+
app:layout_constraintEnd_toEndOf="parent"
15+
app:layout_constraintStart_toStartOf="parent"
16+
app:layout_constraintTop_toTopOf="parent"
17+
tools:ignore="HardcodedText" />
18+
19+
<com.tungsten.fcllibrary.component.view.FCLEditText
20+
android:id="@+id/text"
21+
android:layout_marginTop="10dp"
22+
android:hint="@string/search"
23+
android:layout_width="match_parent"
24+
android:layout_height="wrap_content"
25+
app:layout_constraintStart_toStartOf="parent"
26+
app:layout_constraintTop_toBottomOf="@id/title" />
27+
28+
<androidx.recyclerview.widget.RecyclerView
29+
android:id="@+id/recycler_view"
30+
android:layout_width="match_parent"
31+
android:layout_height="0dp"
32+
app:layout_constraintBottom_toTopOf="@id/cancel"
33+
app:layout_constraintTop_toBottomOf="@id/text" />
34+
35+
<com.tungsten.fcllibrary.component.view.FCLButton
36+
android:id="@+id/cancel"
37+
android:layout_width="wrap_content"
38+
android:layout_height="wrap_content"
39+
android:text="@string/button_cancel"
40+
app:layout_constraintBottom_toBottomOf="parent"
41+
app:layout_constraintEnd_toEndOf="parent" />
42+
43+
</androidx.constraintlayout.widget.ConstraintLayout>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
android:padding="10dp"
5+
android:stateListAnimator="@xml/anim_scale"
6+
android:clickable="true"
7+
android:focusable="true"
8+
android:layout_width="match_parent"
9+
android:layout_height="wrap_content">
10+
11+
<com.tungsten.fcllibrary.component.view.FCLTextView
12+
android:id="@+id/text"
13+
android:layout_width="wrap_content"
14+
android:layout_height="wrap_content"
15+
app:layout_constraintBottom_toBottomOf="parent"
16+
app:layout_constraintStart_toStartOf="parent"
17+
app:layout_constraintTop_toTopOf="parent" />
18+
19+
</androidx.constraintlayout.widget.ConstraintLayout>

FCL/src/main/res/layout/page_download.xml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,10 @@
136136

137137
<com.tungsten.fcllibrary.component.view.FCLButton
138138
android:id="@+id/search"
139-
android:layout_marginBottom="8dp"
140139
android:layout_width="match_parent"
141140
android:layout_height="wrap_content"
142141
android:layout_marginTop="10dp"
142+
android:layout_marginBottom="8dp"
143143
android:singleLine="true"
144144
android:text="@string/search"
145145
app:ripple="true" />
@@ -156,6 +156,16 @@
156156
app:layout_constraintStart_toEndOf="@+id/left"
157157
app:layout_constraintTop_toTopOf="parent">
158158

159+
<com.tungsten.fcllibrary.component.view.FCLImageView
160+
android:id="@+id/translate"
161+
android:layout_width="40dp"
162+
android:layout_height="40dp"
163+
android:layout_gravity="center"
164+
android:layout_marginEnd="5dp"
165+
android:background="@drawable/ic_translation"
166+
android:visibility="gone"
167+
app:use_theme_color="true" />
168+
159169
<com.tungsten.fcllibrary.component.view.FCLTextView
160170
android:id="@+id/page"
161171
android:layout_width="0dp"
@@ -224,8 +234,10 @@
224234
android:dividerHeight="0dp"
225235
app:layout_constraintBottom_toBottomOf="parent"
226236
app:layout_constraintEnd_toEndOf="parent"
237+
app:layout_constraintHorizontal_bias="0.0"
227238
app:layout_constraintStart_toEndOf="@id/left"
228-
app:layout_constraintTop_toBottomOf="@id/list_layout" />
239+
app:layout_constraintTop_toBottomOf="@id/list_layout"
240+
app:layout_constraintVertical_bias="1.0" />
229241

230242
<com.tungsten.fcllibrary.component.view.FCLProgressBar
231243
android:id="@+id/progress"

0 commit comments

Comments
 (0)