Google Play 단독 출시로 정리 + 스토어 제출 자산 준비
iOS 타깃을 제거했다. Apple Developer Program 연 $99 와 맥이 필요한데 아이폰은 기존 웹 PWA 로 이미 커버되므로 비용 대비 실익이 없다고 판단했다. commonMain 중심 구조는 그대로라 iosTarget 만 다시 넣으면 복구된다. 멀티·리그전/커스텀 카드에 '준비 중' 배지를 붙였다. 구현되지 않은 모드가 스토어 스크린샷에서 동작하는 것처럼 보이면 Play 의 허위 표시 정책에 걸린다. store/ 에 Play Console 제출 자산을 모았다: 등록정보 문구, 데이터 보안 설문 답안(릴리스 APK 에 INTERNET 권한이 없음을 aapt2 로 확인), 개인정보처리방침, 피처 그래픽 1024x500, 스토어 아이콘 512x512, 폰 4장 + 태블릿 3장 스크린샷.
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import java.util.Properties
|
||||
@@ -23,14 +22,9 @@ kotlin {
|
||||
compilerOptions { jvmTarget.set(JvmTarget.JVM_17) }
|
||||
}
|
||||
|
||||
// iOS 타깃 — 실제 컴파일은 macOS + Xcode 에서만 가능하다.
|
||||
// 리눅스에서는 설정만 되고 빌드 태스크를 실행하지 않는다.
|
||||
listOf(iosX64(), iosArm64(), iosSimulatorArm64()).forEach { iosTarget ->
|
||||
iosTarget.binaries.framework {
|
||||
baseName = "ComposeApp"
|
||||
isStatic = true
|
||||
}
|
||||
}
|
||||
// iOS 타깃은 뺐다 (2026-09-24 결정). Apple Developer Program 연 $99 + 맥이
|
||||
// 필요해 비용 대비 실익이 없다고 판단. 아이폰은 웹 PWA(tetrig.pages.dev)로 커버한다.
|
||||
// 구조는 commonMain 중심 그대로라, 나중에 iosTarget 만 다시 추가하면 된다.
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
|
||||
@@ -2,7 +2,7 @@ package kr.tkrmagid.tetrig.data
|
||||
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
|
||||
/** 플랫폼 키-값 저장소 (Android SharedPreferences / iOS NSUserDefaults). */
|
||||
/** 플랫폼 키-값 저장소 (Android 는 SharedPreferences). 기기 밖으로 나가지 않는다. */
|
||||
interface Store {
|
||||
fun getString(key: String, default: String): String
|
||||
fun putString(key: String, value: String)
|
||||
|
||||
@@ -64,18 +64,18 @@ fun MainScreen(
|
||||
ModeCard("솔로", "SPRINT · TIME ATTACK · ENDLESS", Palette.Cobalt, s) { showModes = true }
|
||||
}
|
||||
Box(Modifier.weight(1f)) {
|
||||
ModeCard("멀티 · 리그전", "실시간 1:1 랭크 매치 · 배치 10경기", Palette.Safety, s) { onSoon("멀티 · 리그전") }
|
||||
ModeCard("멀티 · 리그전", "실시간 1:1 랭크 매치 · 배치 10경기", Palette.Safety, s, soon = true) { onSoon("멀티 · 리그전") }
|
||||
}
|
||||
Box(Modifier.weight(1f)) {
|
||||
ModeCard("커스텀", "코드로 만들고 참가 · 인원 제한 없음", null, s) { onSoon("커스텀") }
|
||||
ModeCard("커스텀", "코드로 만들고 참가 · 인원 제한 없음", null, s, soon = true) { onSoon("커스텀") }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Box(Modifier.widthIn(max = 720.dp).align(Alignment.CenterHorizontally)) {
|
||||
Column {
|
||||
ModeCard("솔로", "SPRINT · TIME ATTACK · ENDLESS", Palette.Cobalt, s) { showModes = true }
|
||||
ModeCard("멀티 · 리그전", "실시간 1:1 랭크 매치 · 배치 10경기", Palette.Safety, s) { onSoon("멀티 · 리그전") }
|
||||
ModeCard("커스텀", "코드로 만들고 참가 · 인원 제한 없음", null, s) { onSoon("커스텀") }
|
||||
ModeCard("멀티 · 리그전", "실시간 1:1 랭크 매치 · 배치 10경기", Palette.Safety, s, soon = true) { onSoon("멀티 · 리그전") }
|
||||
ModeCard("커스텀", "코드로 만들고 참가 · 인원 제한 없음", null, s, soon = true) { onSoon("커스텀") }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,6 +144,9 @@ private fun ModeCard(
|
||||
sub: String,
|
||||
barColor: Color?,
|
||||
scale: Float,
|
||||
// 아직 구현되지 않은 모드는 카드에 '준비 중' 배지를 달아 둔다. 스토어 스크린샷에
|
||||
// 없는 기능이 있는 것처럼 보이면 Play 정책(허위 표시) 위반이 된다.
|
||||
soon: Boolean = false,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
Box(Modifier.fillMaxWidth().padding(bottom = (14 * scale).dp)) {
|
||||
@@ -159,7 +162,19 @@ private fun ModeCard(
|
||||
.weight(1f)
|
||||
.padding(start = (14 * scale).dp, top = (18 * scale).dp, end = 8.dp),
|
||||
) {
|
||||
Disp(title, size = (26 * scale).sp)
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Disp(title, size = (26 * scale).sp)
|
||||
if (soon) {
|
||||
Spacer(Modifier.width((8 * scale).dp))
|
||||
Box(
|
||||
Modifier
|
||||
.background(Palette.Sub)
|
||||
.padding(horizontal = (7 * scale).dp, vertical = (2 * scale).dp),
|
||||
) {
|
||||
Mono("준비 중", color = Palette.Bone, size = (11 * scale).sp, weight = FontWeight.Bold)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(6.dp))
|
||||
Mono(sub, color = Palette.Sub, size = (12 * scale).sp)
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package kr.tkrmagid.tetrig
|
||||
|
||||
import androidx.compose.ui.window.ComposeUIViewController
|
||||
import kr.tkrmagid.tetrig.ui.App
|
||||
|
||||
@Suppress("unused", "FunctionName")
|
||||
fun MainViewController() = ComposeUIViewController { App() }
|
||||
@@ -1,16 +0,0 @@
|
||||
package kr.tkrmagid.tetrig.data
|
||||
|
||||
import platform.Foundation.NSUserDefaults
|
||||
|
||||
private class IosStore : Store {
|
||||
private val defaults = NSUserDefaults.standardUserDefaults
|
||||
|
||||
override fun getString(key: String, default: String): String =
|
||||
defaults.stringForKey(key) ?: default
|
||||
|
||||
override fun putString(key: String, value: String) {
|
||||
defaults.setObject(value, forKey = key)
|
||||
}
|
||||
}
|
||||
|
||||
actual fun platformStore(): Store = IosStore()
|
||||
Reference in New Issue
Block a user