Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.compose.desktop.application.tasks.AbstractJPackageTask
import org.jetbrains.compose.internal.de.undercouch.gradle.tasks.download.Download

plugins{
Expand Down Expand Up @@ -30,6 +31,11 @@ sourceSets{
srcDirs("src")
}
}
test{
kotlin{
srcDirs("test")
}
}
}

compose.desktop {
Expand Down Expand Up @@ -99,12 +105,177 @@ dependencies {

implementation(libs.compottie)
implementation(libs.kaml)

testImplementation(kotlin("test"))
testImplementation(libs.mockitoKotlin)
testImplementation(libs.junitJupiter)
testImplementation(libs.junitJupiterParams)
}

tasks.compileJava{
options.encoding = "UTF-8"
}

tasks.test {
useJUnitPlatform()
workingDir = file("build/test")
workingDir.mkdirs()
}

tasks.register<Exec>("installCreateDmg") {
onlyIf { org.gradle.internal.os.OperatingSystem.current().isMacOsX }
commandLine("arch", "-arm64", "brew", "install", "--quiet", "create-dmg")
}
tasks.register<Exec>("packageCustomDmg"){
onlyIf { org.gradle.internal.os.OperatingSystem.current().isMacOsX }
group = "compose desktop"

val distributable = tasks.named<AbstractJPackageTask>("createDistributable").get()
dependsOn(distributable, "installCreateDmg")

val packageName = distributable.packageName.get()
val dir = distributable.destinationDir.get()
val dmg = dir.file("../dmg/$packageName-$version.dmg").asFile
val app = dir.file("$packageName.app").asFile

dmg.parentFile.deleteRecursively()
dmg.parentFile.mkdirs()

val extra = mutableListOf<String>()
val isSigned = compose.desktop.application.nativeDistributions.macOS.signing.sign.get()

if(!isSigned) {
val content = """
run 'xattr -d com.apple.quarantine Processing-${version}.dmg' to remove the quarantine flag
""".trimIndent()
val instructions = dmg.parentFile.resolve("INSTRUCTIONS.txt")
instructions.writeText(content)
extra.add("--add-file")
extra.add("INSTRUCTIONS.txt")
extra.add(instructions.path)
extra.add("200")
extra.add("25")
}

commandLine("brew", "install", "--quiet", "create-dmg")

commandLine("create-dmg",
"--volname", packageName,
"--volicon", file("macos/volume.icns"),
"--background", file("macos/background.png"),
"--icon", "$packageName.app", "200", "200",
"--window-pos", "200", "200",
"--window-size", "775", "485",
"--app-drop-link", "500", "200",
"--hide-extension", "$packageName.app",
*extra.toTypedArray(),
dmg,
app
)
}

tasks.register<Exec>("packageCustomMsi"){
onlyIf { org.gradle.internal.os.OperatingSystem.current().isWindows }
dependsOn("createDistributable")
workingDir = file("windows")
group = "compose desktop"

commandLine(
"dotnet",
"build",
"/p:Platform=x64",
"/p:Version=$version",
"/p:DefineConstants=\"Version=$version;\""
)
}

tasks.register("generateSnapConfiguration"){
onlyIf { org.gradle.internal.os.OperatingSystem.current().isLinux }
val distributable = tasks.named<AbstractJPackageTask>("createDistributable").get()
dependsOn(distributable)

val arch = when (System.getProperty("os.arch")) {
"amd64", "x86_64" -> "amd64"
"aarch64" -> "arm64"
else -> System.getProperty("os.arch")
}

val dir = distributable.destinationDir.get()
val content = """
name: ${rootProject.name}
version: ${rootProject.version}
base: core22
summary: A creative coding editor
description: |
Processing is a flexible software sketchbook and a programming language designed for learning how to code.
confinement: strict

apps:
processing:
command: opt/processing/bin/Processing
desktop: opt/processing/lib/processing-Processing.desktop
plugs:
- desktop
- desktop-legacy
- wayland
- x11

parts:
processing:
plugin: dump
source: deb/processing_$version-1_$arch.deb
source-type: deb
stage-packages:
- openjdk-17-jdk
override-prime: |
snapcraftctl prime
chmod -R +x opt/processing/lib/app/resources/jdk-*
""".trimIndent()
dir.file("../snapcraft.yaml").asFile.writeText(content)
}

tasks.register<Exec>("packageSnap"){
onlyIf { org.gradle.internal.os.OperatingSystem.current().isLinux }
dependsOn("packageDeb", "generateSnapConfiguration")
group = "compose desktop"

val distributable = tasks.named<AbstractJPackageTask>("createDistributable").get()
workingDir = distributable.destinationDir.dir("../").get().asFile

commandLine("snapcraft")
}
tasks.register<Zip>("zipDistributable"){
dependsOn("createDistributable")
group = "compose desktop"

val distributable = tasks.named<AbstractJPackageTask>("createDistributable").get()
val dir = distributable.destinationDir.get()
val packageName = distributable.packageName.get()

from(dir){ eachFile{ permissions{ unix("755") } } }
archiveBaseName.set(packageName)
destinationDirectory.set(dir.file("../").asFile)
}

afterEvaluate{
tasks.named("createDistributable").configure{
finalizedBy("zipDistributable")
}
tasks.named("packageDmg").configure{
dependsOn("packageCustomDmg")
group = "compose desktop"
actions = emptyList()
}
tasks.named("packageMsi").configure{
dependsOn("packageCustomMsi")
group = "compose desktop"
actions = emptyList()
}
tasks.named("packageDistributionForCurrentOS").configure {
dependsOn("packageSnap")
}
}


// LEGACY TASKS
// Most of these are shims to be compatible with the old build system
Expand Down
8 changes: 4 additions & 4 deletions app/src/processing/app/Base.java
Original file line number Diff line number Diff line change
Expand Up @@ -1364,10 +1364,10 @@ private File moveLikeSketchFolder(File pdeFile, String baseName) throws IOExcept
* @param schemeUri the full URI, including pde://
*/
public Editor handleScheme(String schemeUri) {
// var result = Schema.handleSchema(schemeUri, this);
// if (result != null) {
// return result;
// }
var result = Schema.handleSchema(schemeUri, this);
if (result != null) {
return result;
}

String location = schemeUri.substring(6);
if (location.length() > 0) {
Expand Down
50 changes: 24 additions & 26 deletions app/src/processing/app/Schema.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ class Schema {
private fun handleSketchUrl(uri: URI): Editor?{
val url = File(uri.path.replace("/url/", ""))

val tempSketchFolder = File(Base.untitledFolder, url.nameWithoutExtension)
val rand = (1..6)
.map { (('a'..'z') + ('A'..'Z')).random() }
.joinToString("")

val tempSketchFolder = File(File(Base.untitledFolder, rand), url.nameWithoutExtension)
tempSketchFolder.mkdirs()
val tempSketchFile = File(tempSketchFolder, "${tempSketchFolder.name}.pde")

Expand Down Expand Up @@ -81,15 +85,15 @@ class Schema {
downloadFiles(uri, code, File(sketchFolder, "code"))
}
options["pde"]?.let{ pde ->
downloadFiles(uri, pde, sketchFolder)
downloadFiles(uri, pde, sketchFolder, "pde")
}
options["mode"]?.let{ mode ->
val modeFile = File(sketchFolder, "sketch.properties")
modeFile.writeText("mode.id=$mode")
}

}
private fun downloadFiles(uri: URI, urlList: String, targetFolder: File){
private fun downloadFiles(uri: URI, urlList: String, targetFolder: File, extension: String = ""){
Thread{
targetFolder.mkdirs()

Expand All @@ -101,37 +105,31 @@ class Schema {
val files = urlList.split(",")

files.filter { it.isNotBlank() }
.map{ it.split(":", limit = 2) }
.map{ segments ->
if(segments.size == 2){
if(segments[0].isBlank()){
return@map listOf(null, segments[1])
}
return@map segments
}
return@map listOf(null, segments[0])
.map {
if (it.contains(":")) it
else "$it:$it"
}
.map{ it.split(":", limit = 2) }
.forEach { (name, content) ->
var target = File(targetFolder, name)
if(extension.isNotBlank() && target.extension != extension){
target = File(targetFolder, "$name.$extension")
}
try{
// Try to decode the content as base64
val file = Base64.getDecoder().decode(content)
if(name == null){
if(name.isBlank()){
Messages.err("Base64 files needs to start with a file name followed by a colon")
return@forEach
}
File(targetFolder, name).writeBytes(file)
target.writeBytes(file)
}catch(_: IllegalArgumentException){
// Assume it's a URL and download it
var url = URI.create(content)
if(url.host == null){
url = URI.create("https://$base/$content")
}
if(url.scheme == null){
url = URI.create("https://$content")
}

val target = File(targetFolder, name ?: url.path.split("/").last())
url.toURL().openStream().use { input ->
val url = URL(when{
content.startsWith("https://") -> content
content.startsWith("http://") -> content.replace("http://", "https://")
URL("https://$content").path.isNotBlank() -> "https://$content"
else -> "https://$base/$content"
})
url.openStream().use { input ->
target.outputStream().use { output ->
input.copyTo(output)
}
Expand Down
Loading
Loading