Skip to content

Commit

Permalink
抽取 #49
Browse files Browse the repository at this point in the history
  • Loading branch information
Soltus committed May 20, 2024
1 parent 2c093a7 commit df57ef4
Show file tree
Hide file tree
Showing 9 changed files with 625 additions and 534 deletions.
55 changes: 52 additions & 3 deletions app/src/main/java/org/b3log/siyuan/ManageSpaceActivity.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
package org.b3log.siyuan

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode
import kotlinx.coroutines.DelicateCoroutinesApi
import org.b3log.siyuan.compose.components.CommonTopAppBar
import org.b3log.siyuan.producer.MyUI

// TODO: 仿哔哩哔哩界面
Expand All @@ -22,12 +41,42 @@ class ManageSpaceActivity : ComponentActivity() {
}
setContent {
CascadeMaterialTheme {
// 改写,抽取重用
MyUI(intent)
UI(intent)
}
}

//设置竖屏锁定
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class, DelicateCoroutinesApi::class)
@Composable
private fun UI(intent: Intent?) {
val TAG = "MainPro-MyUI"
val uri = intent?.data
val Lcc = LocalContext.current
val inspectionMode = LocalInspectionMode.current // 获取当前是否处于预览模式// 获取窗口尺寸
val coroutineScope = rememberCoroutineScope()
val fileName = uri?.let { Us.getFileName(Lcc, it) }
val fileSize = uri?.let { Us.getFileSize(Lcc, it) }
val mimeType = intent?.data?.let { Us.getMimeType(Lcc, it) } ?: ""
val fileType = fileName?.let { Us.getFileMIMEType(mimeType, it) } ?: run { Us.getFileMIMEType(mimeType) }
val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE // 是否横屏(宽高比)

var isMenuVisible by rememberSaveable { mutableStateOf(false) }

Scaffold(
topBar = {
CommonTopAppBar("汐洛存储清理助手", uri) {
// 将Context对象安全地转换为Activity
if (Lcc is Activity) {
Lcc.finish() // 结束活动
}
}
}, modifier = Modifier.background(Color.Gray)
) {

}
}
3 changes: 1 addition & 2 deletions app/src/main/java/org/b3log/siyuan/USB_AUDIO_EXCLUSIVE.kt
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.app.NotificationManagerCompat
import kotlinx.coroutines.launch
import org.b3log.siyuan.producer.getFileName

class USB_AUDIO_EXCLUSIVE : AppCompatActivity() {
private lateinit var usbManager: UsbManager
Expand Down Expand Up @@ -291,7 +290,7 @@ fun MyUI_USB_AUDIO_EXCLUSIVE(activity: USB_AUDIO_EXCLUSIVE) {
contract = ActivityResultContracts.GetContent()
) { uri: Uri? ->
uri?.let {
fileName = getFileName(activity, uri) ?: ""
fileName = Us.getFileName(activity, uri) ?: ""
isPlaying.value = true
isStopped.value = false
// 启动 MusicService 并传递音乐文件的 URI
Expand Down
114 changes: 114 additions & 0 deletions app/src/main/java/org/b3log/siyuan/Us.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.b3log.siyuan

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.KeyguardManager
import android.content.ContentResolver
Expand All @@ -20,6 +21,24 @@ import android.provider.MediaStore
import android.provider.OpenableColumns
import android.provider.Settings
import android.util.Log
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.InsertDriveFile
import androidx.compose.material.icons.filled.Android
import androidx.compose.material.icons.filled.Badge
import androidx.compose.material.icons.filled.Book
import androidx.compose.material.icons.filled.Css
import androidx.compose.material.icons.filled.Description
import androidx.compose.material.icons.filled.FolderZip
import androidx.compose.material.icons.filled.Html
import androidx.compose.material.icons.filled.Image
import androidx.compose.material.icons.filled.Javascript
import androidx.compose.material.icons.filled.Movie
import androidx.compose.material.icons.filled.MusicNote
import androidx.compose.material.icons.filled.PictureAsPdf
import androidx.compose.material.icons.filled.Tab
import androidx.compose.material.icons.filled.TableChart
import androidx.compose.material.icons.filled.TextFields
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.core.app.ActivityCompat
import androidx.core.content.FileProvider
import androidx.documentfile.provider.DocumentFile
Expand Down Expand Up @@ -190,6 +209,31 @@ object Us {
}


fun isFileSizeOverLimit(file: File, limitMB: Int): Boolean {
val fileSize = file.length() // 获取文件大小,单位为字节
val fileSizeInMB = fileSize / (1024 * 1024) // 将文件大小转换为 MB
return fileSizeInMB > limitMB
}
fun isFileSizeOverLimit(contentResolver: ContentResolver, uri: Uri, limitMB: Int): Boolean {
val fileSize = getFileSizeFromUri(contentResolver, uri) ?: return false // 获取文件大小,如果获取失败则返回 false
val fileSizeInMB = fileSize / (1024 * 1024) // 将文件大小转换为 MB
return fileSizeInMB > limitMB
}

/**
* 根据 Uri 获取文件大小
*
* @param contentResolver ContentResolver
* @param uri 目标文件夹的 uri
*/
fun getFileSizeFromUri(contentResolver: ContentResolver, uri: Uri): Long? {
return contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
cursor.moveToFirst()
cursor.getLong(sizeIndex)
}
}

/**
* 从 uri 获取文件路径
*
Expand Down Expand Up @@ -459,6 +503,40 @@ object Us {
return context.contentResolver.getType(uri)
}


//fun getIconForFileType(fileType: String): Int { // 有空再说
// return when (fileType) {
// "视频" -> R.drawable.ic_video
// "音频" -> R.drawable.ic_audio
// "文本" -> R.drawable.ic_text
// "图像" -> R.drawable.ic_image
// "程序" -> R.drawable.ic_program
// else -> R.drawable.ic_file // 默认图标
// }
//}
fun getIconForFileType(fileType: String): ImageVector {
return when {
fileType == "其他文本" -> Icons.Default.TextFields
fileType == "HTML" -> Icons.Default.Html
fileType == "CSS" -> Icons.Default.Css
fileType == "JavaScript" -> Icons.Default.Javascript
fileType == "PDF" -> Icons.Default.PictureAsPdf
fileType == "Word文档" -> Icons.Default.Badge
fileType == "Excel表格" -> Icons.Default.TableChart
fileType == "PowerPoint演示文稿" -> Icons.Default.Tab
fileType == "压缩文件" -> Icons.Default.FolderZip
fileType == "EPUB" -> Icons.Default.Book
fileType.endsWith("视频") -> Icons.Default.Movie
fileType.endsWith("音频") -> Icons.Default.MusicNote
fileType.endsWith("文本") -> Icons.Default.Description
fileType.endsWith("图像") -> Icons.Default.Image
fileType.endsWith("程序") -> Icons.Default.Android
fileType.endsWith("音频") -> Icons.Default.MusicNote
else -> Icons.AutoMirrored.Filled.InsertDriveFile // 默认图标
}
}


fun getFileMIMEType(mimeType: String, fileName: String=""): String {
when {
fileName.endsWith(".apk.1") -> { return "程序" }
Expand Down Expand Up @@ -533,6 +611,42 @@ object Us {
}
}

fun openUrl(url: String) {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
}


fun isStorageSpaceAvailable(contentResolver: ContentResolver, uri: Uri): Boolean {
contentResolver.openFileDescriptor(uri, "r").use { pfd ->
val inputStream = contentResolver.openInputStream(uri)
inputStream?.use { input ->
val fileSize = pfd?.statSize ?: 0
val buffer = ByteArray(8 * 1024) // 缓冲区大小为 8 KB
var bytesRead: Int
var totalBytesRead = 0L
while (input.read(buffer).also { bytesRead = it } != -1) {
totalBytesRead += bytesRead
// 假设存储空间不足的临界值为文件大小的三倍
if (totalBytesRead > fileSize * 3) {
return false
}
}
}
}
return true
}

@SuppressLint("Range")
fun getFileName(context: Context, uri: Uri): String? {
var result: String? = null
context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
if (cursor.moveToFirst()) {
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
}
}
return result
}

fun handleVideo(context: Context, uri: Uri) {
val videoPath = if (uri.scheme == "file") {
// 本地文件
Expand Down
29 changes: 29 additions & 0 deletions app/src/main/java/org/b3log/siyuan/compose/Action.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.b3log.siyuan.compose

import android.annotation.SuppressLint
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp

@SuppressLint("UnrememberedMutableInteractionSource")
@Composable
fun SelectableText(text: String, modifier: Modifier = Modifier, style: TextStyle = TextStyle()) {
// 支持长按选择操作
SelectionContainer {
Text(
text = text,
modifier = modifier,
style = style
.copy(
fontSize = 16.sp,
fontWeight = FontWeight.Normal,
fontStyle = FontStyle.Normal
)
)
}
}
109 changes: 109 additions & 0 deletions app/src/main/java/org/b3log/siyuan/compose/Button.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package org.b3log.siyuan.compose

import android.content.res.Configuration
import android.net.Uri
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.unit.dp
import org.b3log.siyuan.S
import org.b3log.siyuan.Us


@Composable
fun AudioButtons() {
val TAG = "MainPro-BtnPart-AudioButtons"
val inspectionMode = LocalInspectionMode.current // 获取当前是否处于预览模式// 获取窗口尺寸
val Button_Width = S.C.Button_Width.current
val btn_lspace = S.C.btn_lspace.current
val btn_PaddingTopH = S.C.btn_PaddingTopH.current
val btn_PaddingTopV = S.C.btn_PaddingTopV.current
val btn_TextFontsizeH = S.C.btn_TextFontsizeH.current
val btn_TextFontsizeV = S.C.btn_TextFontsizeV.current
val btn_Color1 = S.C.btn_Color1.current
val btn_bgColor1 = S.C.btn_bgColor_pink.current
val btnText1 = S.C.btnTextAudio1.current
val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE // 是否横屏(宽高比)
Button(modifier= Modifier
.width(Button_Width.dp)
.padding(top = if (isLandscape) btn_PaddingTopH else btn_PaddingTopV),
colors = ButtonDefaults.buttonColors(
containerColor = btn_bgColor1,
contentColor = btn_Color1
), enabled = false,
onClick = { /*TODO*/ }) {
Text(
text = btnText1,
letterSpacing = btn_lspace,
fontSize = if (isLandscape) btn_TextFontsizeH else btn_TextFontsizeV
)
}
}

@Composable
fun VideoButtons(uri: Uri) {
val TAG = "MainPro-BtnPart-AudioButtons"
val inspectionMode = LocalInspectionMode.current // 获取当前是否处于预览模式// 获取窗口尺寸
val Lcc = LocalContext.current
val Button_Width = S.C.Button_Width.current
val btn_lspace = S.C.btn_lspace.current
val btn_PaddingTopH = S.C.btn_PaddingTopH.current
val btn_PaddingTopV = S.C.btn_PaddingTopV.current
val btn_TextFontsizeH = S.C.btn_TextFontsizeH.current
val btn_TextFontsizeV = S.C.btn_TextFontsizeV.current
val btn_Color1 = S.C.btn_Color1.current
val btn_bgColor1 = S.C.btn_bgColor_pink.current
val btnText1 = S.C.btnTextVideo1.current
val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE // 是否横屏(宽高比)
Button(modifier= Modifier
.width(Button_Width.dp)
.padding(top = if (isLandscape) btn_PaddingTopH else btn_PaddingTopV),
colors = ButtonDefaults.buttonColors(
containerColor = btn_bgColor1,
contentColor = btn_Color1
), enabled = true, onClick = {
Us.handleVideo(Lcc, uri)
}) {
Text(
text = btnText1,
letterSpacing = btn_lspace,
fontSize = if (isLandscape) btn_TextFontsizeH else btn_TextFontsizeV
)
}
}

@Composable
fun ApkButtons( ApkBTNonClick1: () -> Unit) {
val TAG = "MainPro-BtnPart-AudioButtons"
val inspectionMode = LocalInspectionMode.current // 获取当前是否处于预览模式// 获取窗口尺寸
val Button_Width = S.C.Button_Width.current
val btn_lspace = S.C.btn_lspace.current
val btn_PaddingTopH = S.C.btn_PaddingTopH.current
val btn_PaddingTopV = S.C.btn_PaddingTopV.current
val btn_TextFontsizeH = S.C.btn_TextFontsizeH.current
val btn_TextFontsizeV = S.C.btn_TextFontsizeV.current
val btn_Color1 = S.C.btn_Color1.current
val btn_bgColor1 = S.C.btn_bgColor_pink.current
val btnText1 = S.C.btnText5Apk1.current
val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE // 是否横屏(宽高比)
Button(modifier= Modifier
.width(Button_Width.dp)
.padding(top = if (isLandscape) btn_PaddingTopH else btn_PaddingTopV),
colors = ButtonDefaults.buttonColors(
containerColor = btn_bgColor1,
contentColor = btn_Color1
), enabled = true, onClick = ApkBTNonClick1) {
Text(
text = btnText1,
letterSpacing = btn_lspace,
fontSize = if (isLandscape) btn_TextFontsizeH else btn_TextFontsizeV
)
}
}
Loading

0 comments on commit df57ef4

Please sign in to comment.