Initial commit - v1.1.9
This commit is contained in:
137
app/src/main/java/com/example/shiftalarm/NoticeActivity.kt
Normal file
137
app/src/main/java/com/example/shiftalarm/NoticeActivity.kt
Normal file
@@ -0,0 +1,137 @@
|
||||
package com.example.shiftalarm
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.example.shiftalarm.databinding.ActivityNoticeBinding
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
class NoticeActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityNoticeBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
enableEdgeToEdge()
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityNoticeBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
|
||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
||||
insets
|
||||
}
|
||||
|
||||
supportActionBar?.hide()
|
||||
|
||||
binding.btnCloseNotice.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
binding.noticeRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||
fetchChangelog()
|
||||
}
|
||||
|
||||
private fun fetchChangelog() {
|
||||
// GitHub Raw URL with cache busting
|
||||
val baseUrl = "https://raw.githubusercontent.com/sanjeok77-tech/dakjaba-releases/main/CHANGELOG.md"
|
||||
val urlString = "$baseUrl?t=${System.currentTimeMillis()}"
|
||||
|
||||
Thread {
|
||||
try {
|
||||
val url = URL(urlString)
|
||||
val connection = url.openConnection() as HttpURLConnection
|
||||
connection.connectTimeout = 5000
|
||||
connection.readTimeout = 5000
|
||||
connection.requestMethod = "GET"
|
||||
connection.useCaches = false
|
||||
|
||||
if (connection.responseCode == 200) {
|
||||
val reader = BufferedReader(InputStreamReader(connection.inputStream))
|
||||
val content = reader.use { it.readText() }
|
||||
|
||||
runOnUiThread {
|
||||
val notices = parseChangelog(content)
|
||||
binding.noticeRecyclerView.adapter = NoticeAdapter(notices)
|
||||
}
|
||||
} else {
|
||||
throw Exception("Server returned ${connection.responseCode}")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
runOnUiThread {
|
||||
// Fallback to local asset
|
||||
loadLocalChangelog()
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun loadLocalChangelog() {
|
||||
try {
|
||||
val content = assets.open("CHANGELOG.md").bufferedReader().use { it.readText() }
|
||||
val notices = parseChangelog(content)
|
||||
binding.noticeRecyclerView.adapter = NoticeAdapter(notices)
|
||||
} catch (e: Exception) {
|
||||
val empty = listOf(NoticeItem("데이터 로드 실패", "", "변경사항을 불러올 수 없습니다."))
|
||||
binding.noticeRecyclerView.adapter = NoticeAdapter(empty)
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseChangelog(content: String): List<NoticeItem> {
|
||||
val notices = mutableListOf<NoticeItem>()
|
||||
val lines = content.lines()
|
||||
|
||||
var currentVersion = ""
|
||||
var currentDate = ""
|
||||
var currentBody = StringBuilder()
|
||||
|
||||
for (line in lines) {
|
||||
val trimmed = line.trim()
|
||||
// Skip empty lines or horizontal rules (any amount of dashes)
|
||||
if (trimmed.isEmpty() || trimmed.matches(Regex("-{2,}"))) continue
|
||||
|
||||
// Handle version headers like "## v0.7.3" or "## [0.7.3]"
|
||||
if (trimmed.startsWith("## v") || trimmed.startsWith("## [")) {
|
||||
// Save previous version if exists
|
||||
if (currentVersion.isNotEmpty() && currentBody.isNotBlank()) {
|
||||
notices.add(NoticeItem("v$currentVersion 업데이트 정보", currentDate, currentBody.toString().trim()))
|
||||
}
|
||||
|
||||
// Parse new version (matches v0.7.3 or [0.7.3])
|
||||
val versionMatch = Regex("v?([\\d.]+)").find(trimmed)
|
||||
currentVersion = versionMatch?.groupValues?.getOrNull(1) ?: ""
|
||||
|
||||
val dateMatch = Regex("(\\d{4}-\\d{2}-\\d{2})").find(trimmed)
|
||||
currentDate = dateMatch?.groupValues?.getOrNull(1) ?: ""
|
||||
|
||||
currentBody = StringBuilder()
|
||||
} else if (trimmed.startsWith("- **") || trimmed.startsWith("* **")) {
|
||||
// Content line with bold key
|
||||
val cleaned = trimmed
|
||||
.replace(Regex("^[-*]\\s*\\*\\*(.+?)\\*\\*:?\\s*"), "▸ $1: ")
|
||||
.replace("**", "")
|
||||
currentBody.appendLine(cleaned)
|
||||
} else if (trimmed.startsWith("-") || trimmed.startsWith("*")) {
|
||||
// Regular bullet point
|
||||
val cleaned = trimmed.replace(Regex("^[-*]\\s*"), "• ")
|
||||
if (cleaned.length > 2) currentBody.appendLine(cleaned)
|
||||
}
|
||||
}
|
||||
|
||||
// Add last version
|
||||
if (currentVersion.isNotEmpty() && currentBody.isNotBlank()) {
|
||||
notices.add(NoticeItem("v$currentVersion 업데이트 정보", currentDate, currentBody.toString().trim()))
|
||||
}
|
||||
|
||||
return notices.take(7)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user