Group chat Ui improvements:
- Added Actions modal for one-click access to all actions - Tweaked the top bar and bottom bars - Made it bubbles
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
kotlin version: 2.0.21
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
|
||||
1. Kotlin compile daemon is ready
|
||||
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #2 with error code: 0. The daemon process output:
|
||||
1. Kotlin compile daemon is ready
|
||||
Problems may have occurred during auto-selection of GC. The preferred GC is Parallel GC.
|
||||
If the problems persist, try adding the JVM option to the Kotlin daemon JVM arguments: -XX:-UseParallelGC.
|
||||
GC auto-selection logic is disabled temporary for the next daemon startup.
|
||||
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #3 with error code: 0. The daemon process output:
|
||||
1. Kotlin compile daemon is ready
|
||||
|
||||
error message: Failed connecting to the daemon in 4 retries
|
||||
|
||||
error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
|
||||
java.lang.RuntimeException: Could not connect to Kotlin compile daemon
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76)
|
||||
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
|
||||
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:210)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:205)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:67)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:60)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:167)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:60)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:54)
|
||||
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
|
||||
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
|
||||
at org.gradle.internal.Factories$1.create(Factories.java:31)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:263)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
|
||||
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
|
||||
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
|
||||
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
|
||||
at java.base/java.lang.Thread.run(Thread.java:840)
|
||||
|
||||
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Wisp: Run on Emulator",
|
||||
"type": "node-terminal",
|
||||
"request": "launch",
|
||||
"command": "echo 'Running Wisp on emulator...'",
|
||||
"preLaunchTask": "wisp:run-on-emulator"
|
||||
},
|
||||
{
|
||||
"name": "Wisp: Start Filtered Logcat",
|
||||
"type": "node-terminal",
|
||||
"request": "launch",
|
||||
"command": "echo 'Starting filtered logcat...'",
|
||||
"preLaunchTask": "wisp:logcat"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+55
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "wisp:start-emulator",
|
||||
"type": "shell",
|
||||
"command": "if adb devices | awk '/^emulator-/{found=1} END{exit !found}'; then echo \"Emulator already running\"; else nohup \"$HOME/Library/Android/sdk/emulator/emulator\" -avd Pixel_9_API_35 >/tmp/wisp-emulator.log 2>&1 & echo \"Starting emulator Pixel_9_API_35\"; fi",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "wisp:wait-for-boot",
|
||||
"type": "shell",
|
||||
"command": "adb wait-for-device; echo \"Waiting for Android boot (Package Manager)...\"; i=0; while [ \"$i\" -lt 180 ]; do b=$(adb shell getprop sys.boot_completed 2>/dev/null | xargs); if [ \"$b\" = \"1\" ]; then echo \"Boot complete.\"; exit 0; fi; i=$((i+1)); sleep 2; done; echo \"Timeout: emulator did not finish booting.\"; exit 1",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "wisp:prepare-device-space",
|
||||
"type": "shell",
|
||||
"command": "adb uninstall com.wisp.app >/dev/null 2>&1 || true; adb shell pm trim-caches 2G >/dev/null 2>&1 || true",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "wisp:install-debug",
|
||||
"type": "shell",
|
||||
"command": "export JAVA_HOME=\"/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home\"; export PATH=\"$JAVA_HOME/bin:$PATH\"; ./gradlew :app:assembleDebug && SERIAL=$(adb devices | awk '/^emulator-.*[[:space:]]+device$/{print $1; exit}'); [ -n \"$SERIAL\" ] || SERIAL=$(adb devices | awk '/^[[:alnum:]:.-]+[[:space:]]+device$/{print $1; exit}'); [ -n \"$SERIAL\" ] || { echo \"No adb device in state device\"; exit 1; }; adb -s \"$SERIAL\" install -r app/build/outputs/apk/debug/app-debug.apk",
|
||||
"group": "build",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "wisp:launch-app",
|
||||
"type": "shell",
|
||||
"command": "adb wait-for-device && adb shell monkey -p com.wisp.app -c android.intent.category.LAUNCHER 1",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "wisp:run-on-emulator",
|
||||
"dependsOrder": "sequence",
|
||||
"dependsOn": [
|
||||
"wisp:start-emulator",
|
||||
"wisp:wait-for-boot",
|
||||
"wisp:prepare-device-space",
|
||||
"wisp:install-debug",
|
||||
"wisp:launch-app"
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "wisp:logcat",
|
||||
"type": "shell",
|
||||
"command": "if command -v rg >/dev/null 2>&1; then adb logcat | rg --line-buffered \"AndroidRuntime|FATAL EXCEPTION|System.err|wisp|Wisp\"; else adb logcat; fi",
|
||||
"isBackground": true,
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1553,6 +1553,7 @@ fun WispNavHost(
|
||||
val groupRoomUploadScope = rememberCoroutineScope()
|
||||
var groupRoomUploadProgress by remember { mutableStateOf<String?>(null) }
|
||||
var groupRoomZapTarget by remember { mutableStateOf<com.wisp.app.nostr.NostrEvent?>(null) }
|
||||
var groupRoomZapInitialSats by remember { mutableStateOf<Int?>(null) }
|
||||
var showGroupRoomEmojiLibrary by remember { mutableStateOf(false) }
|
||||
val groupRoomResolvedEmojis by feedViewModel.customEmojiRepo.resolvedEmojis.collectAsState()
|
||||
val groupRoomUnicodeEmojis by feedViewModel.customEmojiRepo.sortedUnicodeEmojis.collectAsState()
|
||||
@@ -1580,14 +1581,19 @@ fun WispNavHost(
|
||||
}
|
||||
ZapDialog(
|
||||
isWalletConnected = isNwcConnected,
|
||||
onDismiss = { groupRoomZapTarget = null },
|
||||
onDismiss = {
|
||||
groupRoomZapTarget = null
|
||||
groupRoomZapInitialSats = null
|
||||
},
|
||||
onZap = { amountMsats, message, isAnonymous, isPrivate ->
|
||||
val event = groupRoomZapTarget ?: return@ZapDialog
|
||||
groupRoomZapTarget = null
|
||||
groupRoomZapInitialSats = null
|
||||
feedViewModel.sendZap(event, amountMsats, message, isAnonymous, isPrivate)
|
||||
},
|
||||
onGoToWallet = { navController.navigateSafe(Routes.WALLET) },
|
||||
canPrivateZap = feedViewModel.relayPool.hasDmRelays() && recipientHasDmRelays
|
||||
canPrivateZap = feedViewModel.relayPool.hasDmRelays() && recipientHasDmRelays,
|
||||
initialSatsHint = groupRoomZapInitialSats
|
||||
)
|
||||
}
|
||||
val groupRoomMediaLauncher = rememberLauncherForActivityResult(
|
||||
@@ -1652,6 +1658,27 @@ fun WispNavHost(
|
||||
uploadProgress = groupRoomUploadProgress,
|
||||
myPubkey = feedViewModel.getUserPubkey(),
|
||||
onZap = { msgId, senderPubkey ->
|
||||
groupRoomZapInitialSats = null
|
||||
groupRoomZapTarget = com.wisp.app.nostr.NostrEvent(
|
||||
id = msgId,
|
||||
pubkey = senderPubkey,
|
||||
created_at = 0L,
|
||||
kind = com.wisp.app.nostr.Nip29.KIND_CHAT_MESSAGE,
|
||||
tags = listOf(listOf("h", groupId)),
|
||||
content = "",
|
||||
sig = ""
|
||||
)
|
||||
feedViewModel.relayPool.sendToRelayOrEphemeral(
|
||||
relayUrl,
|
||||
com.wisp.app.nostr.ClientMessage.req(
|
||||
subscriptionId = "zap-rcpt-grp-${msgId.take(12)}",
|
||||
filter = com.wisp.app.nostr.Filter(kinds = listOf(9735), eTags = listOf(msgId))
|
||||
),
|
||||
skipBadCheck = true
|
||||
)
|
||||
},
|
||||
onZapPreset = { msgId, senderPubkey, sats ->
|
||||
groupRoomZapInitialSats = sats
|
||||
groupRoomZapTarget = com.wisp.app.nostr.NostrEvent(
|
||||
id = msgId,
|
||||
pubkey = senderPubkey,
|
||||
@@ -1661,8 +1688,6 @@ fun WispNavHost(
|
||||
content = "",
|
||||
sig = ""
|
||||
)
|
||||
// Subscribe to zap receipt on the group relay too, in case the
|
||||
// LNURL provider publishes it there
|
||||
feedViewModel.relayPool.sendToRelayOrEphemeral(
|
||||
relayUrl,
|
||||
com.wisp.app.nostr.ClientMessage.req(
|
||||
|
||||
@@ -53,6 +53,7 @@ import androidx.compose.material3.SwitchDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -102,7 +103,9 @@ fun ZapDialog(
|
||||
onDismiss: () -> Unit,
|
||||
onZap: (amountMsats: Long, message: String, isAnonymous: Boolean, isPrivate: Boolean) -> Unit,
|
||||
onGoToWallet: () -> Unit,
|
||||
canPrivateZap: Boolean = false
|
||||
canPrivateZap: Boolean = false,
|
||||
/** When opening from a quick preset (e.g. chat actions sheet), pre-select that amount in sats. */
|
||||
initialSatsHint: Int? = null
|
||||
) {
|
||||
if (!isWalletConnected) {
|
||||
AlertDialog(
|
||||
@@ -134,6 +137,22 @@ fun ZapDialog(
|
||||
var isPrivate by remember { mutableStateOf(false) }
|
||||
var editMode by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(initialSatsHint) {
|
||||
val hint = initialSatsHint ?: return@LaunchedEffect
|
||||
val h = hint.toLong().coerceAtLeast(1L)
|
||||
val fromPrefs = ZapPreferences(context).getPresets().sortedBy { it.amountSats }
|
||||
val match = fromPrefs.find { it.amountSats == h }
|
||||
if (match != null) {
|
||||
selectedPreset = match
|
||||
isCustom = false
|
||||
message = match.message
|
||||
} else {
|
||||
isCustom = true
|
||||
customAmount = h.toString()
|
||||
message = ""
|
||||
}
|
||||
}
|
||||
|
||||
val effectiveAmount = if (isCustom) {
|
||||
customAmount.toLongOrNull() ?: 0L
|
||||
} else {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -238,6 +238,16 @@
|
||||
<string name="error_no_relay_scores">No relay scores available yet</string>
|
||||
<string name="btn_add_to_set">+Set</string>
|
||||
<string name="btn_details">Details</string>
|
||||
<string name="group_room_comment">Comment</string>
|
||||
<string name="group_room_section_zap">Zap</string>
|
||||
<string name="group_room_section_actions">Actions</string>
|
||||
<string name="group_room_eyebrow_react">REACT</string>
|
||||
<string name="group_room_eyebrow_zap">ZAP</string>
|
||||
<string name="group_room_eyebrow_actions">ACTIONS</string>
|
||||
<string name="cd_open_full_zap">Open zap dialog</string>
|
||||
<string name="cd_open_reaction_picker">Open reaction picker</string>
|
||||
<string name="cd_send_options">Send options</string>
|
||||
<string name="send_options_coming_soon">Send options coming soon.</string>
|
||||
|
||||
<!-- Content Descriptions -->
|
||||
<string name="cd_back">Back</string>
|
||||
|
||||
Reference in New Issue
Block a user