Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ abstract class FeedbackImpl {
// Implementation-specific functions
abstract fun logMessage(str: String, level: FeedbackLevel)

open fun getTimestamp(): Long = System.nanoTime() / 1_000_000

// Global public functions
fun setLevel(lvl: FeedbackLevel) {
logLevel = lvl
Expand Down Expand Up @@ -199,7 +201,7 @@ abstract class FeedbackImpl {
++messages.first().count
} else {
// Prepend new message and pop last if buffer is full
val msg = FeedbackMessage(str, 1, System.currentTimeMillis(), level)
val msg = FeedbackMessage(str, 1, getTimestamp(), level)
if (messages.size == maxMessages) messages.removeLast()
messages.addFirst(msg)
}
Expand Down
7 changes: 7 additions & 0 deletions designcompose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,15 @@ android {

testFixtures { enable = true }

buildFeatures { buildConfig = true }

defaultConfig {
minSdk = libs.versions.minSdk.get().toInt()
buildConfigField(
"String",
"DESIGNCOMPOSE_VERSION",
"\"${libs.versions.designcompose.get()}\"",
)
consumerProguardFiles("consumer-proguard-rules.pro")
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
if (designcompose.figmaToken.isPresent) {
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import android.util.Log
import androidx.annotation.VisibleForTesting
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand All @@ -38,8 +39,17 @@ import kotlinx.coroutines.launch

// Need to rename all of this to use "Access Token" instead of "Auth Key". This will match Figma's
// terminology: https://help.figma.com/hc/en-us/articles/8085703771159-Manage-personal-access-tokens

var ACTION_SET_API_KEY = "setApiKey"
var EXTRA_SET_API_KEY = "ApiKey"
var ACTION_ENABLE_LIVE_UPDATE = "enableLiveUpdate"
var EXTRA_ENABLE_LIVE_UPDATE = "Enabled"
var ACTION_SET_AUTOPAUSE_TIMEOUT = "setAutopauseTimeout"
var EXTRA_AUTOPAUSE_TIMEOUT = "TimeoutMs"
var ACTION_SET_LIVE_UPDATE_FETCH_MILLIS = "setLiveUpdateFetchMillis"
var EXTRA_LIVE_UPDATE_FETCH_MILLIS = "FetchIntervalMs"
var ACTION_ENABLE_ADAPTIVE_POLLING = "enableAdaptivePolling"
var EXTRA_ADAPTIVE_POLLING_ENABLED = "Enabled"

class ApiKeyService : Service() {

Expand All @@ -53,17 +63,60 @@ class ApiKeyService : Service() {

private val binder = ApiKeyBinder()

override fun onBind(intent: Intent): IBinder {
if (intent.action == "setFigmaKey") {
setApiKey(intent.getStringExtra("ApiKey"))
private fun processIntent(intent: Intent) {
val action = intent.action
val valueString =
when (action) {
ACTION_SET_API_KEY,
"setFigmaKey" -> ""
ACTION_ENABLE_LIVE_UPDATE ->
", value: ${intent.getBooleanExtra(EXTRA_ENABLE_LIVE_UPDATE, true)}"
ACTION_SET_AUTOPAUSE_TIMEOUT ->
", value: ${intent.getLongExtra(EXTRA_AUTOPAUSE_TIMEOUT, -1)}"
ACTION_SET_LIVE_UPDATE_FETCH_MILLIS ->
", value: ${intent.getLongExtra(EXTRA_LIVE_UPDATE_FETCH_MILLIS, -1)}"
ACTION_ENABLE_ADAPTIVE_POLLING ->
", value: ${intent.getBooleanExtra(EXTRA_ADAPTIVE_POLLING_ENABLED, true)}"
else -> ""
}
Log.i(TAG, "ApiKeyService received intent action: $action$valueString")

when (action) {
ACTION_SET_API_KEY,
"setFigmaKey" -> {
setApiKey(
intent.getStringExtra(EXTRA_SET_API_KEY) ?: intent.getStringExtra("ApiKey")
)
}
ACTION_ENABLE_LIVE_UPDATE -> {
setLiveUpdateEnabled(intent.getBooleanExtra(EXTRA_ENABLE_LIVE_UPDATE, true))
}
ACTION_SET_AUTOPAUSE_TIMEOUT -> {
val timeout = intent.getLongExtra(EXTRA_AUTOPAUSE_TIMEOUT, -1)
if (timeout != -1L) setAutopauseTimeout(timeout)
}
ACTION_SET_LIVE_UPDATE_FETCH_MILLIS -> {
val interval = intent.getLongExtra(EXTRA_LIVE_UPDATE_FETCH_MILLIS, -1)
if (interval != -1L) setLiveUpdateFetchMillis(interval)
}
ACTION_ENABLE_ADAPTIVE_POLLING -> {
setAdaptivePollingEnabled(
intent.getBooleanExtra(EXTRA_ADAPTIVE_POLLING_ENABLED, true)
)
}
else -> {
Log.w(TAG, "ApiKeyService received unknown intent action: $action")
}
}
}

override fun onBind(intent: Intent): IBinder {
processIntent(intent)
return binder
}

override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
if (intent.action == ACTION_SET_API_KEY) {
intent.getStringExtra(EXTRA_SET_API_KEY)?.let { key -> setApiKey(key) }
}
processIntent(intent)
stopSelf()
return START_NOT_STICKY
}
Expand All @@ -75,4 +128,28 @@ class ApiKeyService : Service() {
}
}
}

fun setLiveUpdateEnabled(enabled: Boolean) {
CoroutineScope(dispatcher).launch {
DesignSettings.liveUpdateSettings?.setLiveUpdateEnabled(enabled)
}
}

fun setAutopauseTimeout(timeoutMs: Long) {
CoroutineScope(dispatcher).launch {
DesignSettings.liveUpdateSettings?.setLiveUpdateTimeout(timeoutMs)
}
}

fun setLiveUpdateFetchMillis(intervalMs: Long) {
CoroutineScope(dispatcher).launch {
DesignSettings.liveUpdateSettings?.setLiveUpdateFetchMillis(intervalMs)
}
}

fun setAdaptivePollingEnabled(enabled: Boolean) {
CoroutineScope(dispatcher).launch {
DesignSettings.liveUpdateSettings?.setAdaptivePollingEnabled(enabled)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ private interface DesignSwitcher {
enum class LiveMode {
Live,
Offline,
Paused,
}

enum class TopStatusBar {
Expand Down Expand Up @@ -162,6 +163,7 @@ private interface DesignSwitcher {
doc_text_edit: @Composable ((ComponentReplacementContext) -> Unit)?,
show_help_text: Boolean,
on_tap_go: TapCallback,
on_tap_live_mode: TapCallback,
node_names_checkbox: ReplacementContent,
mini_messages_checkbox: ReplacementContent,
show_recomposition_checkbox: ReplacementContent,
Expand All @@ -182,6 +184,7 @@ private interface DesignSwitcher {
customizations.setComponent("#DocIdTextEdit", doc_text_edit)
customizations.setVisible("#HelpText", show_help_text)
customizations.setTapCallback("#GoButton", on_tap_go)
customizations.setTapCallback("#LiveMode", on_tap_live_mode)
customizations.setContent("#NodeNamesCheckbox", node_names_checkbox)
customizations.setContent("#MiniMessagesCheckbox", mini_messages_checkbox)
customizations.setContent("#ShowRecompositionCheckbox", show_recomposition_checkbox)
Expand Down Expand Up @@ -414,7 +417,7 @@ private fun GetMessages(docId: DesignDocId): ReplacementContent {
{
val it = messages[index]
val message = if (it.count > 1) it.message + "(${it.count})" else it.message
val secondsAgo = (System.currentTimeMillis() - it.timestamp) / 1000
val secondsAgo = (android.os.SystemClock.uptimeMillis() - it.timestamp) / 1000
if (it.level == FeedbackLevel.Error || it.level == FeedbackLevel.Warn)
DesignSwitcherDoc.MessageFailed(message, elapsedTimeString(secondsAgo))
else DesignSwitcherDoc.Message(message, elapsedTimeString(secondsAgo))
Expand Down Expand Up @@ -597,14 +600,24 @@ internal fun DesignSwitcher(
setDocId(DesignDocId(docIdText))
}
},
on_tap_live_mode = {
if (DesignSettings.liveUpdatesEnabled) {
if (DocServer.pauseUpdates.value) {
DocServer.startLiveUpdates()
} else {
DocServer.stopLiveUpdates()
}
}
},
node_names_checkbox = GetNodeNamesCheckbox(nodeNamesChecked, setNodeNamesChecked),
mini_messages_checkbox =
GetMiniMessagesCheckbox(miniMessagesChecked, setMiniMessagesChecked),
show_recomposition_checkbox =
GetShowRecompositionCheckbox(showRecompositionChecked, setShowRecompositionChecked),
useLocalResCheckbox = GetUseLocalResCheckbox(useLocalResChecked, setUseLocalResChecked),
live_mode =
if (DesignSettings.isDocumentLive.value) DesignSwitcher.LiveMode.Live
if (DocServer.pauseUpdates.value) DesignSwitcher.LiveMode.Paused
else if (DesignSettings.isDocumentLive.value) DesignSwitcher.LiveMode.Live
else DesignSwitcher.LiveMode.Offline,
top_status_bar = topStatusBar,
)
Expand Down
Loading
Loading