汐洛 v0.28.24 发布,基于思源 v3.0.8 构建

本贴最后更新于 226 天前,其中的信息可能已经时过境迁

这是一个中等质量的版本更新,与思源 v3.0.8 版本对齐,包含思源 v3.0.7 和 v3.0.6 的累积更新。

更新重点分析

汐洛文件中转站

通用处理助手添加了文件中转站功能,借鉴了 ES 文件管理器的实现。这是新增功能,有很多不完善的地方,比如操作不当会产生大量应用缓存,目前还没有针对处理。保存到指定文件夹目前使用字符串硬拼接,在部分机型上可能无效。

c87d774ed8f23286a1ef0975bc25d1a7.jpg

提高前端控制台输出覆盖率

现在所有端使用 print 调试大法都更加方便了,副作用是有时候不得不筛选输出。

修复了上个版本存在的问题

上个版本在平板上启动闪退的问题在这个版本已经得到了修复。

提供汐洛版本号而非思源版本号导致的兼容性问题也得到了修复。

安卓端申请电源优化无限制权限与悬浮窗权限失败的问题也得到了修复。主要通过 EventBus 实现。

安卓端重启软件丢失锁定态的问题也得到了修复。主要通过 MMKV 读写实现。

更新摘要

@Sillot

改进功能 | Enhancement

修复错误 | Bugfix

闪亮之名 | Shinning

@Sillot-android

引入特性 | Feature

改进功能 | Enhancement

修复错误 | Bugfix

移除废止 | Abolishment

部分更新核心代码

文件中转站 UI 代码

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class, DelicateCoroutinesApi::class)
@Composable
fun MyUI(intent: Intent?, fileType: String?, context: Context) {
    val TAG = "MainPro-MyUI"
    val uri = intent?.data
    val coroutineScope = rememberCoroutineScope()
    val fileName = uri?.let { getFileName(context, it) }
    val fileSize = uri?.let { getFileSize(it) }
//    val mimeType = intent?.data?.let { getMimeType(context, it) }
//    val fileType = mimeType?.let { getFileType(it) }
    val Thumbnail_Height = 250
    val Button_Width = 300
    val btn_lspace = 0.1.em
    val btn_PaddingTopH = 3.dp
    val btn_PaddingTopV = 6.dp
    val btn_TextFontsizeH = 20.sp
    val btn_TextFontsizeV = 18.sp
    val btn_Color1 = Color.White
    val btn_bgColor1 = Color(0xFF2196F3)
    val btn_bgColor2 = Color(0xFF1976D2)
    val btn_bgColor3 = Color(0xFF2391B5)
    val btn_bgColor4 = Color(0xFF237A58)
    val btnText1 = "分享"
    val btnText2 = "复制到剪贴板"
    val btnText3 = "保存到指定文件夹"
    val btnText4 = "存入工作空间级资源目录"
    var progressValue by remember { mutableStateOf(0) }
    var isButton3OnClickRunning by remember { mutableStateOf(false) }
    var isButton4OnClickRunning by remember { mutableStateOf(false) }
    var destinationDir by remember {
        mutableStateOf(File(context.getExternalFilesDir(null), "sillot/data/assets"))
    }
    var sourceFile by remember {
        mutableStateOf(uri?.let { getFileFromUri(context, it) })
    }
    var selectedFolder by remember { mutableStateOf<Uri?>(null) }

    val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            result.data?.data?.let { uri ->
                // Get the selected folder path from the URI
                selectedFolder = uri
            }
        }
    }
    val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE

    LaunchedEffect(key1 = isButton3OnClickRunning) {
        if (isButton3OnClickRunning && selectedFolder!=null) {
            // 启动一个协程来执行任务
            coroutineScope.launch {
                withContext(Dispatchers.IO) {
                    var inputStream: BufferedInputStream? = null
                    var outputStream: BufferedOutputStream? = null

                    try {
                        inputStream = BufferedInputStream(FileInputStream(sourceFile))
                        val destinationFile =
                            (fileName ?: sourceFile?.name)?.let { File(destinationDir, it) }
                        outputStream = BufferedOutputStream(FileOutputStream(destinationFile))

                        val buffer = ByteArray(1024 * 64) // 64KB的缓冲区
                        val totalBytes = sourceFile?.length()
                        var bytesCopied = 0L

                        var bytesRead: Int
                        while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                            outputStream.write(buffer, 0, bytesRead)
                            bytesCopied += bytesRead

                            if (totalBytes != null) {
                                progressValue = (bytesCopied.toFloat() / totalBytes.toFloat() * 100).toInt()
                            }
                        }
                    } catch (e: IOException) {
                        e.printStackTrace()
                    } finally {
                        outputStream?.flush()
                        outputStream?.close()
                        inputStream?.close()
                    }
                }
                withContext(Dispatchers.Main) {
                    Toast.Show(context, "已复制到指定文件夹")
                }
                // 执行任务完成后,关闭遮罩
                isButton3OnClickRunning = false
                selectedFolder = null
            }
        }
    }
    LaunchedEffect(key1 = isButton4OnClickRunning) {
        if (isButton4OnClickRunning) {
            // 启动一个协程来执行任务
            coroutineScope.launch {
                withContext(Dispatchers.IO) {
                    var inputStream: BufferedInputStream? = null
                    var outputStream: BufferedOutputStream? = null

                    try {
                        inputStream = BufferedInputStream(FileInputStream(sourceFile))
                        val destinationFile =
                            (fileName ?: sourceFile?.name)?.let { File(destinationDir, it) }
                        outputStream = BufferedOutputStream(FileOutputStream(destinationFile))

                        val buffer = ByteArray(1024 * 64) // 64KB的缓冲区
                        val totalBytes = sourceFile?.length()
                        var bytesCopied = 0L

                        var bytesRead: Int
                        while (inputStream!!.read(buffer).also { bytesRead = it } != -1) {
                            outputStream!!.write(buffer, 0, bytesRead)
                            bytesCopied += bytesRead

                            if (totalBytes != null) {
                                progressValue = (bytesCopied.toFloat() / totalBytes.toFloat() * 100).toInt()
                            }
                        }
                    } catch (e: IOException) {
                        e.printStackTrace()
                    } finally {
                        outputStream?.flush()
                        outputStream?.close()
                    Button(modifier= Modifier
                        .width(Button_Width.dp)
                        .padding(top = btn_PaddingTopV),
                        colors = ButtonDefaults.buttonColors(
                            containerColor = btn_bgColor3,
                            contentColor = btn_Color1
                        ), enabled = true, onClick = {
                        val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
                        launcher.launch(intent)
                        // 非阻塞
                    }) {
                        Text(
                            text = btnText3,
                            letterSpacing = btn_lspace,
                            fontSize = btn_TextFontsizeV
                        )
                    }

                    Button(modifier= Modifier
                        .width(Button_Width.dp)
                        .padding(top = btn_PaddingTopV),
                        colors = ButtonDefaults.buttonColors(
                            containerColor = btn_bgColor4,
                            contentColor = btn_Color1
                        ), enabled = true, onClick = {
                        if (uri!=null) {
                            coroutineScope.launch {
                                destinationDir = File(context.getExternalFilesDir(null), "sillot/data/assets")
                                sourceFile = getFileFromUri(context, uri)
                                if (sourceFile == null || isFileSizeOverLimit(context.contentResolver, uri, 5858)) {
                                    withContext(Dispatchers.Main) {
                                        Toast.Show(context, "暂不支持超大文件或文件不存在")
                                    }
                                } else {
                                    Log.e(TAG,destinationDir.toString())
                                    isButton4OnClickRunning = true // 值变化时会触发重组
                                }
                            }
                        }
                    }) {
                        Text(
                            text = btnText4,
                            letterSpacing = btn_lspace,
                            fontSize = btn_TextFontsizeV
                        )
                    }
                    Spacer(modifier = Modifier.height(16.dp))


                    selectedFolder?.let { folder ->
                        val folderPath = "/storage/emulated/0/" + (folder.lastPathSegment?.split(":")
                            ?.last() ?: "")
                        if (folderPath!="") {
                            Log.e(TAG, "Selected Folder: $folderPath")
                            Text("Selected Folder: $folderPath")
                            destinationDir = File(folderPath)
                            sourceFile = uri?.let { it1 -> getFileFromUri(context, it1) }
                            isButton3OnClickRunning = true // 值变化时会触发重组
                        }
                    }
                }
            }

        }

    }
}

  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 85 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...