Skip to content

Commit

Permalink
Automatically extract icon and image when they are missing (#43)
Browse files Browse the repository at this point in the history
* Automatically extract icon and image when they are missing

* code cleanup
  • Loading branch information
lings03 authored Dec 31, 2024
1 parent 405ad13 commit e562ea4
Show file tree
Hide file tree
Showing 15 changed files with 232 additions and 163 deletions.
1 change: 0 additions & 1 deletion app/src/main/kotlin/top/laoxin/modmanager/bean/ModBean.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package top.laoxin.modmanager.bean

import android.os.Parcel
import android.os.Parcelable
import android.util.Log
import androidx.room.Entity
import androidx.room.PrimaryKey

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ package top.laoxin.modmanager.bean

import androidx.room.Entity
import androidx.room.PrimaryKey
import java.sql.Time
import java.util.Date

@Entity(tableName = "scanFiles")
data class ScanFileBean (
@PrimaryKey(autoGenerate = true) val id: Int = 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package top.laoxin.modmanager.database.sacnFile

import kotlinx.coroutines.flow.Flow
import top.laoxin.modmanager.bean.BackupBean
import top.laoxin.modmanager.bean.ScanFileBean

class OfflineScanFileRepository(private val scanFileDao: ScanFileDao) : ScanFileRepository {
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/kotlin/top/laoxin/modmanager/tools/LogTools.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ object LogTools {
if (!logFile.exists()) {
logFile.createNewFile()
} else {
logFile.writeText("")
logFile.delete()
logFile.createNewFile()
}

val executor = Executors.newSingleThreadExecutor()
Expand Down
9 changes: 6 additions & 3 deletions app/src/main/kotlin/top/laoxin/modmanager/tools/ModTools.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ object ModTools {
val BACKUP_PATH = MY_APP_PATH + "backup/"
private val MODS_TEMP_PATH = MY_APP_PATH + "temp/"
val MODS_UNZIP_PATH = MY_APP_PATH + "temp/unzip/"
private val MODS_ICON_PATH = MY_APP_PATH + "icon/"
private val MODS_IMAGE_PATH = MY_APP_PATH + "images/"
val MODS_ICON_PATH = MY_APP_PATH + "icon/"
val MODS_IMAGE_PATH = MY_APP_PATH + "images/"
const val GAME_CONFIG = "GameConfig/"
const val DOWNLOAD_MOD_PATH = "/Download/Mods/"
val GAME_CHECK_FILE_PATH = MY_APP_PATH + "gameCheckFile/"
Expand Down Expand Up @@ -381,6 +381,7 @@ object ModTools {
val modFileName = File(file).name
val gameFileMap = mutableMapOf<String, String>()
if (!gameInfo.isGameFileRepeat) {
// 如果游戏文件路径不重复
gameFileMap.apply {
gameInfo.gameFilePath.forEachIndexed { index, _ ->
put(
Expand All @@ -390,6 +391,7 @@ object ModTools {
}
}
} else {
// 如果游戏文件路径重复
gameFileMap.apply {
gameInfo.gameFilePath.forEachIndexed { index, it ->
val pathName = File(it).name
Expand Down Expand Up @@ -435,7 +437,8 @@ object ModTools {
isZip = if (archiveFile == null) false else ArchiveUtil.isArchive(
archiveFile.absolutePath
),
modPath = if (archiveFile == null) File(file).parent ?: file else archiveFile.absolutePath,
modPath = if (archiveFile == null) File(file).parent
?: file else archiveFile.absolutePath,
virtualPaths = if (archiveFile == null) "" else archiveFile.absolutePath
+ File(file).parentFile?.absolutePath
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import androidx.core.graphics.drawable.toBitmap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ fun AllModPage(
modsSelected = uiState.modsSelected,
onLongClick = viewModel::modLongClick,
onMultiSelectClick = viewModel::modMultiSelectClick,
modViewModel = viewModel
)
}

Expand Down
228 changes: 102 additions & 126 deletions app/src/main/kotlin/top/laoxin/modmanager/ui/view/modView/Mod.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,61 +20,34 @@ package top.laoxin.modmanager.ui.view.modView
import android.content.Context
import android.graphics.Bitmap
import android.util.Log
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Snackbar
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
Expand Down Expand Up @@ -115,7 +88,8 @@ fun ModPage(viewModel: ModViewModel) {
switchMod = { mod, enable -> viewModel.switchMod(mod, enable, true) },
onConfirmRequest = {
viewModel.delMods()
}
},
viewModel = viewModel
)
DialogCommon(
title = stringResource(R.string.open_mod_failed_dialog_title),
Expand Down Expand Up @@ -210,6 +184,7 @@ fun DisEnableModsDialog(
mods: List<ModBean>,
switchMod: (ModBean, Boolean) -> Unit,
onConfirmRequest: () -> Unit,
viewModel: ModViewModel
) {
if (showDialog) {
if (mods.isNotEmpty()) {
Expand All @@ -231,7 +206,8 @@ fun DisEnableModsDialog(
enableMod = switchMod,
isMultiSelect = false,
onLongClick = { },
onMultiSelectClick = { }
onMultiSelectClick = { },
modViewModel = viewModel
)
Spacer(modifier = Modifier.height(8.dp))
}
Expand Down Expand Up @@ -272,109 +248,109 @@ suspend fun loadImageBitmapFromPath(
.get()
bitmap.asImageBitmap()
} catch (e: Exception) {
e.printStackTrace()
Log.e("loadImageBitmapFromPath", "加载图片失败: $e")
null
}
}
}


/**
* @param hint: 空字符时的提示
* @param startIcon: 左侧图标; -1 则不显示
* @param iconSpacing: 左侧图标与文字的距离; 相当于: drawablePadding
*/
@Composable
fun CustomEdit(
text: String = "",
onValueChange: (String) -> Unit,
modifier: Modifier,
hint: String = "请输入",
@DrawableRes startIcon: Int = -1,
iconSpacing: Dp = 6.dp,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
visualTransformation: VisualTransformation = VisualTransformation.None,
cursorBrush: Brush = SolidColor(MaterialTheme.colorScheme.primary),
close: () -> Unit
) {
// 焦点, 用于控制是否显示 右侧叉号
var hasFocus by remember { mutableStateOf(false) }
val focusRequester = remember { FocusRequester() }

BasicTextField(
value = text,
onValueChange = onValueChange,
modifier = modifier
.focusRequester(focusRequester)
.onFocusChanged {
if (!it.isFocused && hasFocus) {
// 组件失去焦点
close()
}
hasFocus = it.isFocused
},
singleLine = true,
enabled = enabled,
readOnly = readOnly,
textStyle = textStyle,
keyboardOptions = keyboardOptions,
keyboardActions = KeyboardActions(onDone = { close() }),
visualTransformation = visualTransformation,
cursorBrush = cursorBrush,
decorationBox = @Composable { innerTextField ->
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
// -1 不显示 左侧Icon
if (startIcon != -1) {
Image(painter = painterResource(id = startIcon), contentDescription = null)
Spacer(modifier = Modifier.width(iconSpacing))
}

Box(modifier = Modifier.weight(1f)) {
// 当空字符时, 显示hint
if (text.isEmpty())
Text(text = hint, color = Color.Gray, style = textStyle)

// 原本输入框的内容
innerTextField()
}

// 存在焦点 且 有输入内容时. 显示叉号
if (hasFocus && text.isNotEmpty()) {
Log.d("CustomEdit", "CustomEdit:失去焦点 ")

Icon(imageVector = Icons.Filled.Clear, // 清除图标
contentDescription = null,
tint = MaterialTheme.colorScheme.primaryContainer,
// 点击就清空text
modifier = Modifier.clickable {
onValueChange.invoke("")
})
}
Icon(
imageVector = Icons.Filled.Search,
contentDescription = null,
tint = MaterialTheme.colorScheme.primaryContainer,

modifier = Modifier
.clickable {
close()
}
.padding(start = 10.dp)
)
}
}
)

LaunchedEffect(focusRequester) {
focusRequester.requestFocus()
}
}
///**
// * @param hint: 空字符时的提示
// * @param startIcon: 左侧图标; -1 则不显示
// * @param iconSpacing: 左侧图标与文字的距离; 相当于: drawablePadding
// */
//@Composable
//fun CustomEdit(
// text: String = "",
// onValueChange: (String) -> Unit,
// modifier: Modifier,
// hint: String = "请输入",
// @DrawableRes startIcon: Int = -1,
// iconSpacing: Dp = 6.dp,
// enabled: Boolean = true,
// readOnly: Boolean = false,
// textStyle: TextStyle = TextStyle.Default,
// keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
// visualTransformation: VisualTransformation = VisualTransformation.None,
// cursorBrush: Brush = SolidColor(MaterialTheme.colorScheme.primary),
// close: () -> Unit
//) {
// // 焦点, 用于控制是否显示 右侧叉号
// var hasFocus by remember { mutableStateOf(false) }
// val focusRequester = remember { FocusRequester() }
//
// BasicTextField(
// value = text,
// onValueChange = onValueChange,
// modifier = modifier
// .focusRequester(focusRequester)
// .onFocusChanged {
// if (!it.isFocused && hasFocus) {
// // 组件失去焦点
// close()
// }
// hasFocus = it.isFocused
// },
// singleLine = true,
// enabled = enabled,
// readOnly = readOnly,
// textStyle = textStyle,
// keyboardOptions = keyboardOptions,
// keyboardActions = KeyboardActions(onDone = { close() }),
// visualTransformation = visualTransformation,
// cursorBrush = cursorBrush,
// decorationBox = @Composable { innerTextField ->
// Row(
// modifier = Modifier.fillMaxWidth(),
// verticalAlignment = Alignment.CenterVertically
// ) {
// // -1 不显示 左侧Icon
// if (startIcon != -1) {
// Image(painter = painterResource(id = startIcon), contentDescription = null)
// Spacer(modifier = Modifier.width(iconSpacing))
// }
//
// Box(modifier = Modifier.weight(1f)) {
// // 当空字符时, 显示hint
// if (text.isEmpty())
// Text(text = hint, color = Color.Gray, style = textStyle)
//
// // 原本输入框的内容
// innerTextField()
// }
//
// // 存在焦点 且 有输入内容时. 显示叉号
// if (hasFocus && text.isNotEmpty()) {
// Log.d("CustomEdit", "CustomEdit:失去焦点 ")
//
// Icon(imageVector = Icons.Filled.Clear, // 清除图标
// contentDescription = null,
// tint = MaterialTheme.colorScheme.primaryContainer,
// // 点击就清空text
// modifier = Modifier.clickable {
// onValueChange.invoke("")
// })
// }
// Icon(
// imageVector = Icons.Filled.Search,
// contentDescription = null,
// tint = MaterialTheme.colorScheme.primaryContainer,
//
// modifier = Modifier
// .clickable {
// close()
// }
// .padding(start = 10.dp)
// )
// }
// }
// )
//
// LaunchedEffect(focusRequester) {
// focusRequester.requestFocus()
// }
//}


// 创建一个占据全屏的居中文本, 提示没有mod
Expand Down
Loading

0 comments on commit e562ea4

Please sign in to comment.