Skip to content

Commit

Permalink
💄 Support file pasted item preview (#377)
Browse files Browse the repository at this point in the history
  • Loading branch information
guiyanakuang authored Feb 25, 2024
1 parent 34cf44f commit e740fbd
Show file tree
Hide file tree
Showing 29 changed files with 347 additions and 45 deletions.
10 changes: 0 additions & 10 deletions composeApp/src/commonMain/kotlin/com/clipevery/ClipeveryApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.toComposeImageBitmap
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.dp
import com.clipevery.ui.AboutView
Expand Down Expand Up @@ -115,11 +113,3 @@ fun ClipeveryContent() {
}
}
}

fun loadImageBitmap(resourcePath: String): ImageBitmap {
// Assuming `resourcePath` is a valid path for an image file within your resources directory.
val image = org.jetbrains.skia.Image.makeFromEncoded(
Thread.currentThread().contextClassLoader.getResourceAsStream(resourcePath)
?.readBytes()!!)
return image.toComposeImageBitmap()
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import java.nio.file.Path

interface ClipFile {

var isFile: Boolean

fun getFilePath(): Path

fun getExtension(): String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ interface ClipAppearItem {
}
}

fun sortClipAppearItems(clipAppearItems: List<ClipAppearItem>): List<ClipAppearItem> {
return clipAppearItems.sortedBy { it.getClipType() }
}

data class ClipAppearItemId(val clipType: Int, val md5: String) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ import androidx.compose.ui.window.PopupProperties
import com.clipevery.LocalExitApplication
import com.clipevery.LocalKoinApplication
import com.clipevery.i18n.GlobalCopywriter
import com.clipevery.loadImageBitmap
import com.clipevery.ui.base.ClipIconButton
import com.clipevery.utils.ResourceUtils.loadImageBitmap
import java.awt.Desktop
import java.net.URI

Expand Down
99 changes: 99 additions & 0 deletions composeApp/src/commonMain/kotlin/com/clipevery/ui/base/ClipIcon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,103 @@ fun image(): ImageVector {
}
.build()
}
}

@Composable
fun file(): ImageVector {
return remember {
ImageVector.Builder(
name = "File", defaultWidth = 24.0.dp, defaultHeight = 24.0.dp,
viewportWidth = 960.0f, viewportHeight = 960.0f
).apply {
path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f,
strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f,
pathFillType = NonZero) {
moveTo(320.0f, 720.0f)
horizontalLineToRelative(320.0f)
verticalLineToRelative(-80.0f)
lineTo(320.0f, 640.0f)
verticalLineToRelative(80.0f)
close()
moveTo(320.0f, 560.0f)
horizontalLineToRelative(320.0f)
verticalLineToRelative(-80.0f)
lineTo(320.0f, 480.0f)
verticalLineToRelative(80.0f)
close()
moveTo(240.0f, 880.0f)
quadToRelative(-33.0f, 0.0f, -56.5f, -23.5f)
reflectiveQuadTo(160.0f, 800.0f)
verticalLineToRelative(-640.0f)
quadToRelative(0.0f, -33.0f, 23.5f, -56.5f)
reflectiveQuadTo(240.0f, 80.0f)
horizontalLineToRelative(320.0f)
lineToRelative(240.0f, 240.0f)
verticalLineToRelative(480.0f)
quadToRelative(0.0f, 33.0f, -23.5f, 56.5f)
reflectiveQuadTo(720.0f, 880.0f)
lineTo(240.0f, 880.0f)
close()
moveTo(520.0f, 360.0f)
verticalLineToRelative(-200.0f)
lineTo(240.0f, 160.0f)
verticalLineToRelative(640.0f)
horizontalLineToRelative(480.0f)
verticalLineToRelative(-440.0f)
lineTo(520.0f, 360.0f)
close()
moveTo(240.0f, 160.0f)
verticalLineToRelative(200.0f)
verticalLineToRelative(-200.0f)
verticalLineToRelative(640.0f)
verticalLineToRelative(-640.0f)
close()
}
}
.build()
}
}

@Composable
fun folder(): ImageVector {
return remember {
ImageVector.Builder(
name = "Folder", defaultWidth = 24.0.dp, defaultHeight = 24.0.dp,
viewportWidth = 960.0f, viewportHeight = 960.0f
).apply {
path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f,
strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f,
pathFillType = NonZero) {
moveTo(160.0f, 800.0f)
quadToRelative(-33.0f, 0.0f, -56.5f, -23.5f)
reflectiveQuadTo(80.0f, 720.0f)
verticalLineToRelative(-480.0f)
quadToRelative(0.0f, -33.0f, 23.5f, -56.5f)
reflectiveQuadTo(160.0f, 160.0f)
horizontalLineToRelative(240.0f)
lineToRelative(80.0f, 80.0f)
horizontalLineToRelative(320.0f)
quadToRelative(33.0f, 0.0f, 56.5f, 23.5f)
reflectiveQuadTo(880.0f, 320.0f)
verticalLineToRelative(400.0f)
quadToRelative(0.0f, 33.0f, -23.5f, 56.5f)
reflectiveQuadTo(800.0f, 800.0f)
lineTo(160.0f, 800.0f)
close()
moveTo(160.0f, 720.0f)
horizontalLineToRelative(640.0f)
verticalLineToRelative(-400.0f)
lineTo(447.0f, 320.0f)
lineToRelative(-80.0f, -80.0f)
lineTo(160.0f, 240.0f)
verticalLineToRelative(480.0f)
close()
moveTo(160.0f, 720.0f)
verticalLineToRelative(-480.0f)
verticalLineToRelative(480.0f)
close()
}
}
.build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ fun ClipPreviewItemView(clipData: ClipData, isLast: Boolean, clipContent: @Compo
if (it.getClipType() == ClipType.TEXT ||
it.getClipType() == ClipType.URL ||
it.getClipType() == ClipType.HTML ||
it.getClipType() == ClipType.IMAGE
it.getClipType() == ClipType.IMAGE ||
it.getClipType() == ClipType.FILE
) {

var hover by remember { mutableStateOf(false) }
Expand Down Expand Up @@ -154,6 +155,7 @@ fun ClipSpecificPreviewItemView(clipData: ClipData) {
ClipType.URL -> UrlPreviewView(clipData)
ClipType.HTML -> HtmlPreviewView(clipData)
ClipType.IMAGE -> ImagePreviewView(clipData)
ClipType.FILE -> FilePreviewView(clipData)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.clipevery.ui.clip

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.clipevery.LocalKoinApplication
import com.clipevery.clip.item.ClipFile
import com.clipevery.dao.clip.ClipData
import com.clipevery.i18n.GlobalCopywriter
import com.clipevery.ui.base.file
import com.clipevery.ui.base.folder
import com.clipevery.utils.FileExtUtils.getExtImage
import com.clipevery.utils.FileUtils

@Composable
fun FilePreviewView(clipData: ClipData) {
clipData.getClipItem(ClipFile::class)?.let {
val current = LocalKoinApplication.current
val copywriter = current.koin.get<GlobalCopywriter>()
val fileUtils = current.koin.get<FileUtils>()

val imageBitmap: ImageBitmap? = remember(it.getExtension()) {
getExtImage(it.getExtension())
}

val isFile: Boolean = remember(it) {
it.isFile
}

val fileSize = remember(it) {
fileUtils.formatBytes(fileUtils.getFileSize(it.getFilePath()))
}

Row(modifier = Modifier.fillMaxSize()
.padding(10.dp),
horizontalArrangement = Arrangement.SpaceBetween
) {
Row {
imageBitmap?.let {
Image(
modifier = Modifier.size(100.dp)
.clip(RoundedCornerShape(5.dp)),
bitmap = it,
contentDescription = "fileType"
)
} ?: run {
Icon(
modifier = Modifier.size(100.dp),
imageVector = if (isFile) file() else folder(),
contentDescription = "fileType",
tint = MaterialTheme.colors.onBackground
)
}

Column(
modifier = Modifier.fillMaxHeight()
.wrapContentWidth()
.padding(horizontal = 8.dp),
verticalArrangement = Arrangement.Bottom
) {
Text(
text = "${copywriter.getText("File_Name")}: ${fileUtils.getFileNameFromRelativePath(it.getFilePath())}",
color = MaterialTheme.colors.onBackground,
style = TextStyle(
fontWeight = FontWeight.Light,
color = MaterialTheme.colors.onBackground,
fontSize = 10.sp
)
)

Text(
text = "${copywriter.getText("Size")}: $fileSize",
color = MaterialTheme.colors.onBackground,
style = TextStyle(
fontWeight = FontWeight.Light,
color = MaterialTheme.colors.onBackground,
fontSize = 10.sp
)
)
}
}

Row(
modifier = Modifier.wrapContentWidth()
.padding(end = 8.dp),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically
) {
Icon(
file(),
contentDescription = "File",
modifier = Modifier.padding(3.dp).size(14.dp),
tint = MaterialTheme.colors.onBackground
)

Text(
text = copywriter.getText("File"),
fontFamily = FontFamily.SansSerif,
style = TextStyle(
fontWeight = FontWeight.Light,
color = MaterialTheme.colors.onBackground,
fontSize = 10.sp
)
)
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.clipevery.utils

import androidx.compose.ui.graphics.ImageBitmap

object FileExtUtils {

private val extImageMap = mapOf(
Pair("pdf", "pdf"),
Pair("doc", "word"),
Pair("docx", "word"),
Pair("ppt", "ppt"),
Pair("pptx", "ppt"),
Pair("xls", "excel"),
Pair("xlsx", "excel"),
Pair("pages", "pages"),
Pair("key", "keynote"),
Pair("numbers", "numbers")
)

fun getExtImage(ext: String): ImageBitmap? =
extImageMap[ext]?.let { ResourceUtils.loadImageBitmap("file-ext/$it.png") }
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.clipevery.utils

import com.clipevery.app.AppFileType
import java.nio.file.Path

interface FileUtils {
Expand All @@ -14,9 +15,11 @@ interface FileUtils {

fun getFileNameFromRelativePath(relativePath: Path): String

fun createClipPath(fileRelativePath: String, isFile: Boolean, isImage: Boolean = false): Path
fun createClipPath(fileRelativePath: String, isFile: Boolean, appFileType: AppFileType): Path

fun getFileSize(path: Path): Long

fun getFileMd5(path: Path): String

fun copyFile(src: Path, dest: Path): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.clipevery.utils

import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.toComposeImageBitmap

object ResourceUtils {

fun loadImageBitmap(resourcePath: String): ImageBitmap {
// Assuming `resourcePath` is a valid path for an image file within your resources directory.
val image = org.jetbrains.skia.Image.makeFromEncoded(
Thread.currentThread().contextClassLoader.getResourceAsStream(resourcePath)
?.readBytes()!!)
return image.toComposeImageBitmap()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.clipevery.clip.TransferableConsumer
import com.clipevery.clip.getDesktopClipboardService
import com.clipevery.clip.plugin.ImageHtmlCombinePlugin
import com.clipevery.clip.plugin.MultiImagePlugin
import com.clipevery.clip.plugin.SortPlugin
import com.clipevery.clip.plugin.UrlTextCombinePlugin
import com.clipevery.clip.service.FileItemService
import com.clipevery.clip.service.HtmlItemService
Expand Down Expand Up @@ -130,7 +131,10 @@ object Dependencies {
UrlItemService()
), listOf(UrlTextCombinePlugin,
ImageHtmlCombinePlugin,
MultiImagePlugin)) }
MultiImagePlugin,
SortPlugin
)
) }

// ui component
single<AppUI> { AppUI(width = 460.dp, height = 710.dp) }
Expand Down
Loading

0 comments on commit e740fbd

Please sign in to comment.