Skip to content

Commit 752f950

Browse files
authored
Merge pull request #1686 from maxrave-dev/dev
v1.0.3: New version
2 parents df906f4 + 5aa82f3 commit 752f950

File tree

17 files changed

+906
-355
lines changed

17 files changed

+906
-355
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ I use [Sentry](http://sentry.io) crashlytics to catch all crashes in the Full ve
101101
- For macOS: Download the file with extension `.dmg`.
102102
- For Linux: Download the file with extension `.deb` (Debian based), `.rpm` (Red-hat based), `.AppImage` (all Linux distributions) .
103103

104+
***Caution***: Not support ARM in Windows and Linux version now, only x86-64. But in macOS version, both ARM and x86-64 are supported.
105+
104106
### Log in guide: https://www.simpmusic.org/blogs/en/how-to-log-in-on-desktop-app
105107

106108
### Some limitations on Desktop app:

composeApp/appimage/simpmusic.desktop

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ Exec=bin/SimpMusic
66
Icon=simpmusic
77
Terminal=false
88
Categories=Audio;AudioVideo;
9+
StartupWMClass=java-lang-Thread

composeApp/build.gradle.kts

Lines changed: 79 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import org.jetbrains.compose.desktop.application.tasks.AbstractJPackageTask
88
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
99
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
1010
import java.net.URI
11+
import java.time.Instant
12+
import java.time.ZoneId
13+
import java.time.format.DateTimeFormatter
1114
import java.util.Properties
1215

1316
val isFullBuild: Boolean =
@@ -26,6 +29,7 @@ plugins {
2629
alias(libs.plugins.kotlin.serialization)
2730
alias(libs.plugins.build.config)
2831
alias(libs.plugins.osdetector)
32+
alias(libs.plugins.packagedeps)
2933
}
3034

3135
kotlin {
@@ -66,8 +70,7 @@ kotlin {
6670
val koinBom = project.dependencies.platform(libs.koin.bom)
6771
implementation(composeBom)
6872
implementation(koinBom)
69-
70-
implementation("commons-io:commons-io:2.5")
73+
implementation(libs.commons.io)
7174
}
7275
androidMain.dependencies {
7376
api(libs.koin.android)
@@ -120,6 +123,8 @@ kotlin {
120123
api(libs.coil.compose)
121124
api(libs.coil.network.okhttp)
122125
api(libs.kmpalette.core)
126+
api(libs.kmpalette.network)
127+
implementation(libs.ktor.client.cio)
123128

124129
// DataStore
125130
implementation(libs.datastore.preferences)
@@ -159,6 +164,7 @@ kotlin {
159164
implementation(compose.desktop.currentOs)
160165
implementation(libs.kotlinx.coroutinesSwing)
161166
implementation(libs.sentry.jvm)
167+
implementation(libs.native.tray)
162168
implementation(projects.mediaJvmUi)
163169
}
164170
}
@@ -170,21 +176,31 @@ compose.desktop {
170176

171177
nativeDistributions {
172178
val listTarget = mutableListOf<TargetFormat>()
173-
if (org.gradle.internal.os.OperatingSystem.current().isMacOsX) {
179+
if (org.gradle.internal.os.OperatingSystem
180+
.current()
181+
.isMacOsX
182+
) {
174183
listTarget.addAll(
175-
listOf(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb, TargetFormat.Rpm)
184+
listOf(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb, TargetFormat.Rpm),
176185
)
177186
} else {
178187
listTarget.addAll(
179-
listOf(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb, TargetFormat.Rpm, TargetFormat.AppImage)
188+
listOf(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb, TargetFormat.Rpm, TargetFormat.AppImage),
180189
)
181190
}
182191
targetFormats(*listTarget.toTypedArray())
183192
modules("jdk.unsupported")
184193
packageName = "SimpMusic"
185194
macOS {
195+
val formatedDate =
196+
Instant.now().let {
197+
DateTimeFormatter
198+
.ofPattern("yyyy.MM.dd")
199+
.withZone(ZoneId.of("UTC"))
200+
.format(it)
201+
}
186202
includeAllModules = true
187-
packageVersion = "2025.12.24"
203+
packageVersion = formatedDate
188204
iconFile.set(project.file("icon/circle_app_icon.icns"))
189205
val macExtraPlistKeys =
190206
"""
@@ -276,6 +292,10 @@ aboutLibraries {
276292
}
277293
}
278294

295+
linuxDebConfig {
296+
startupWMClass.set("java-lang-Thread")
297+
}
298+
279299
afterEvaluate {
280300
tasks.withType<JavaExec> {
281301
jvmArgs("--add-opens", "java.desktop/sun.awt=ALL-UNNAMED")
@@ -307,75 +327,75 @@ afterEvaluate {
307327
return
308328
}
309329

310-
val appimagetool =
311-
layout.buildDirectory
312-
.dir("tmp")
313-
.get()
314-
.asFile
315-
.resolve("appimagetool-x86_64.AppImage")
330+
val appimagetool =
331+
layout.buildDirectory
332+
.dir("tmp")
333+
.get()
334+
.asFile
335+
.resolve("appimagetool-x86_64.AppImage")
316336

317-
if (!appimagetool.exists()) {
318-
downloadFile(
319-
"https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage",
320-
appimagetool,
321-
)
322-
}
337+
if (!appimagetool.exists()) {
338+
downloadFile(
339+
"https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage",
340+
appimagetool,
341+
)
342+
}
323343

324-
if (!appimagetool.canExecute()) {
325-
appimagetool.setExecutable(true)
326-
}
344+
if (!appimagetool.canExecute()) {
345+
appimagetool.setExecutable(true)
346+
}
327347

328-
val appDir =
329-
if (isRelease) {
330-
layout.buildDirectory
331-
.dir("appimage/main-release/$appName.AppDir")
332-
.get()
333-
.asFile
334-
} else {
335-
layout.buildDirectory
336-
.dir("appimage/main/$appName.AppDir")
337-
.get()
338-
.asFile
339-
}
340-
if (appDir.exists()) {
341-
appDir.deleteRecursively()
348+
val appDir =
349+
if (isRelease) {
350+
layout.buildDirectory
351+
.dir("appimage/main-release/$appName.AppDir")
352+
.get()
353+
.asFile
354+
} else {
355+
layout.buildDirectory
356+
.dir("appimage/main/$appName.AppDir")
357+
.get()
358+
.asFile
342359
}
360+
if (appDir.exists()) {
361+
appDir.deleteRecursively()
362+
}
343363

344-
FileUtils.copyDirectory(appDirSrc, appDir)
345-
FileUtils.copyDirectory(packageOutput, appDir)
364+
FileUtils.copyDirectory(appDirSrc, appDir)
365+
FileUtils.copyDirectory(packageOutput, appDir)
346366

347-
val appExecutable = appDir.resolve("bin/$appName")
348-
if (!appExecutable.canExecute()) {
349-
appimagetool.setExecutable(true)
350-
}
367+
val appExecutable = appDir.resolve("bin/$appName")
368+
if (!appExecutable.canExecute()) {
369+
appimagetool.setExecutable(true)
370+
}
351371

352-
val appRun = appDir.resolve("AppRun")
353-
if (!appRun.canExecute()) {
354-
appRun.setReadable(true, false) // readable by all
355-
appRun.setWritable(true, true) // writable only by owner
356-
appRun.setExecutable(true, false)
372+
val appRun = appDir.resolve("AppRun")
373+
if (!appRun.canExecute()) {
374+
appRun.setReadable(true, false) // readable by all
375+
appRun.setWritable(true, true) // writable only by owner
376+
appRun.setExecutable(true, false)
357377

358-
println(
359-
"Set AppRun executable permissions, readable: ${appRun.canRead()}, writable: ${appRun.canWrite()}, executable: ${appRun.canExecute()}",
360-
)
361-
}
378+
println(
379+
"Set AppRun executable permissions, readable: ${appRun.canRead()}, writable: ${appRun.canWrite()}, executable: ${appRun.canExecute()}",
380+
)
381+
}
362382

363-
// Use ProcessBuilder instead of exec {} to avoid capturing project reference
364-
val process = ProcessBuilder(
383+
// Use ProcessBuilder instead of exec {} to avoid capturing project reference
384+
val process =
385+
ProcessBuilder(
365386
appimagetool.canonicalPath,
366387
"$appName.AppDir",
367-
"$appName-x86_64.AppImage"
368-
)
369-
.directory(appDir.parentFile)
388+
"$appName-x86_64.AppImage",
389+
).directory(appDir.parentFile)
370390
.apply { environment()["ARCH"] = "x86_64" } // TODO: 支持arm64
371391
.inheritIO()
372392
.start()
373393

374-
val exitCode = process.waitFor()
375-
if (exitCode != 0) {
376-
throw GradleException("appimagetool failed with exit code $exitCode")
377-
}
394+
val exitCode = process.waitFor()
395+
if (exitCode != 0) {
396+
throw GradleException("appimagetool failed with exit code $exitCode")
378397
}
398+
}
379399

380400
tasks.findByName("packageAppImage")?.doLast {
381401
packAppImage(false)

composeApp/src/commonMain/composeResources/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,4 +518,8 @@
518518
<string name="downvote">Downvote</string>
519519
<string name="vote_submitted">Thank you for voting this lyrics!</string>
520520
<string name="vote_error">Failed to submit</string>
521+
<string name="open_app">Open SimpMusic</string>
522+
<string name="close_miniplayer">Close Mini-player</string>
523+
<string name="open_miniplayer">Open Mini-player</string>
524+
<string name="quit_app">Quit app</string>
521525
</resources>

composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/component/AnimationComponents.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ import androidx.compose.animation.core.infiniteRepeatable
88
import androidx.compose.animation.core.rememberInfiniteTransition
99
import androidx.compose.animation.core.tween
1010
import androidx.compose.foundation.background
11+
import androidx.compose.foundation.border
1112
import androidx.compose.foundation.layout.Box
1213
import androidx.compose.foundation.layout.padding
1314
import androidx.compose.foundation.shape.RoundedCornerShape
1415
import androidx.compose.material3.MaterialTheme
1516
import androidx.compose.material3.Surface
16-
import androidx.compose.runtime.*
1717
import androidx.compose.runtime.Composable
1818
import androidx.compose.runtime.LaunchedEffect
1919
import androidx.compose.runtime.getValue
20+
import androidx.compose.runtime.mutableStateOf
2021
import androidx.compose.runtime.saveable.rememberSaveable
2122
import androidx.compose.runtime.setValue
2223
import androidx.compose.ui.Alignment
@@ -31,6 +32,7 @@ import androidx.compose.ui.graphics.drawscope.rotate
3132
import androidx.compose.ui.graphics.drawscope.scale
3233
import androidx.compose.ui.unit.Dp
3334
import androidx.compose.ui.unit.dp
35+
import com.maxrave.simpmusic.ui.theme.md_theme_dark_background
3436
import kotlinx.coroutines.delay
3537

3638
/**
@@ -82,13 +84,14 @@ fun InfiniteBorderAnimationView(
8284
}
8385
}
8486
},
87+
color = backgroundColor,
8588
shape = shape,
8689
) {
8790
Box(
8891
modifier =
8992
Modifier
9093
.background(
91-
color = backgroundColor,
94+
color = if (isAnimated) md_theme_dark_background else backgroundColor,
9295
).padding(
9396
contentPadding,
9497
),

composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/ui/component/LyricsView.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ fun RichSyncLyricsLineItem(
467467
currentTimeMs: Long,
468468
isCurrent: Boolean,
469469
customFontSize: TextUnit? = null,
470+
customPadding: Dp = 12.dp,
470471
modifier: Modifier = Modifier,
471472
) {
472473
// Performance optimization: derive current word index based on timeline
@@ -482,7 +483,7 @@ fun RichSyncLyricsLineItem(
482483
Column(
483484
modifier = modifier,
484485
) {
485-
Spacer(modifier = Modifier.height(12.dp))
486+
Spacer(modifier = Modifier.height(customPadding))
486487

487488
// Original lyrics with rich sync highlighting - using FlowRow for word wrapping
488489
FlowRow(
@@ -532,7 +533,7 @@ fun RichSyncLyricsLineItem(
532533
)
533534
}
534535

535-
Spacer(modifier = Modifier.height(12.dp))
536+
Spacer(modifier = Modifier.height(customPadding))
536537
}
537538
}
538539

0 commit comments

Comments
 (0)