mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Add support for /rainbow and /rainbowme command (#879)
This commit is contained in:
parent
75e39535bc
commit
e9ea69f055
@ -8,7 +8,7 @@ Improvements 🙌:
|
||||
- Sharing things to RiotX: sort list by recent room first (#771)
|
||||
|
||||
Other changes:
|
||||
-
|
||||
- Add support for /rainbow and /rainbowme commands (#879)
|
||||
|
||||
Bugfix 🐛:
|
||||
-
|
||||
|
@ -37,6 +37,8 @@ enum class Command(val command: String, val parameters: String, @StringRes val d
|
||||
KICK_USER("/kick", "<user-id> [reason]", R.string.command_description_kick_user),
|
||||
CHANGE_DISPLAY_NAME("/nick", "<display-name>", R.string.command_description_nick),
|
||||
MARKDOWN("/markdown", "<on|off>", R.string.command_description_markdown),
|
||||
RAINBOW("/rainbow", "<message>", R.string.command_description_rainbow),
|
||||
RAINBOW_EMOTE("/rainbowme", "<message>", R.string.command_description_rainbow_emote),
|
||||
CLEAR_SCALAR_TOKEN("/clear_scalar_token", "", R.string.command_description_clear_scalar_token),
|
||||
SPOILER("/spoiler", "<message>", R.string.command_description_spoiler);
|
||||
|
||||
|
@ -80,6 +80,16 @@ object CommandParser {
|
||||
|
||||
ParsedCommand.SendEmote(message)
|
||||
}
|
||||
Command.RAINBOW.command -> {
|
||||
val message = textMessage.subSequence(Command.RAINBOW.command.length, textMessage.length).trim()
|
||||
|
||||
ParsedCommand.SendRainbow(message)
|
||||
}
|
||||
Command.RAINBOW_EMOTE.command -> {
|
||||
val message = textMessage.subSequence(Command.RAINBOW_EMOTE.command.length, textMessage.length).trim()
|
||||
|
||||
ParsedCommand.SendRainbowEmote(message)
|
||||
}
|
||||
Command.JOIN_ROOM.command -> {
|
||||
if (messageParts.size >= 2) {
|
||||
val roomAlias = messageParts[1]
|
||||
|
@ -34,6 +34,8 @@ sealed class ParsedCommand {
|
||||
// Valid commands:
|
||||
|
||||
class SendEmote(val message: CharSequence) : ParsedCommand()
|
||||
class SendRainbow(val message: CharSequence) : ParsedCommand()
|
||||
class SendRainbowEmote(val message: CharSequence) : ParsedCommand()
|
||||
class BanUser(val userId: String, val reason: String?) : ParsedCommand()
|
||||
class UnbanUser(val userId: String, val reason: String?) : ParsedCommand()
|
||||
class SetUserPowerLevel(val userId: String, val powerLevel: Int) : ParsedCommand()
|
||||
|
@ -56,6 +56,7 @@ import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventConten
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.matrix.rx.unwrap
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.extensions.postLiveEvent
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
@ -64,6 +65,7 @@ import im.vector.riotx.core.utils.LiveEvent
|
||||
import im.vector.riotx.core.utils.subscribeLogError
|
||||
import im.vector.riotx.features.command.CommandParser
|
||||
import im.vector.riotx.features.command.ParsedCommand
|
||||
import im.vector.riotx.features.home.room.detail.composer.rainbow.RainbowGenerator
|
||||
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
|
||||
import im.vector.riotx.features.home.room.typing.TypingHelper
|
||||
import im.vector.riotx.features.settings.VectorPreferences
|
||||
@ -83,6 +85,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val stringProvider: StringProvider,
|
||||
private val typingHelper: TypingHelper,
|
||||
private val rainbowGenerator: RainbowGenerator,
|
||||
private val session: Session
|
||||
) : VectorViewModel<RoomDetailViewState, RoomDetailAction, RoomDetailViewEvents>(initialState), Timeline.Listener {
|
||||
|
||||
@ -385,6 +388,20 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||
_sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandHandled())
|
||||
popDraft()
|
||||
}
|
||||
is ParsedCommand.SendRainbow -> {
|
||||
slashCommandResult.message.toString().let {
|
||||
room.sendFormattedTextMessage(it, rainbowGenerator.generate(it))
|
||||
}
|
||||
_sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandHandled())
|
||||
popDraft()
|
||||
}
|
||||
is ParsedCommand.SendRainbowEmote -> {
|
||||
slashCommandResult.message.toString().let {
|
||||
room.sendFormattedTextMessage(it, rainbowGenerator.generate(it), MessageType.MSGTYPE_EMOTE)
|
||||
}
|
||||
_sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandHandled())
|
||||
popDraft()
|
||||
}
|
||||
is ParsedCommand.SendSpoiler -> {
|
||||
room.sendFormattedTextMessage(
|
||||
"[${stringProvider.getString(R.string.spoiler)}](${slashCommandResult.message})",
|
||||
@ -401,7 +418,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||
// TODO
|
||||
_sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandNotImplemented)
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
is SendMode.EDIT -> {
|
||||
// is original event a reply?
|
||||
@ -459,7 +476,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||
popDraft()
|
||||
}
|
||||
}
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.home.room.detail.composer.rainbow
|
||||
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Inspired from React-Sdk
|
||||
* Ref: https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/utils/colour.js
|
||||
*/
|
||||
class RainbowGenerator @Inject constructor() {
|
||||
|
||||
fun generate(text: String): String {
|
||||
val frequency = 360f / text.length
|
||||
|
||||
return text
|
||||
.mapIndexed { idx, letter ->
|
||||
// Do better than React-Sdk: Avoid adding font color for spaces
|
||||
if (letter == ' ') {
|
||||
"$letter"
|
||||
} else {
|
||||
val dashColor = hueToRGB(idx * frequency, 1.0f, 0.5f).toDashColor()
|
||||
"<font color=\"$dashColor\">$letter</font>"
|
||||
}
|
||||
}
|
||||
.joinToString(separator = "")
|
||||
}
|
||||
|
||||
private fun hueToRGB(h: Float, s: Float, l: Float): RgbColor {
|
||||
val c = s * (1 - abs(2 * l - 1))
|
||||
val x = c * (1 - abs((h / 60) % 2 - 1))
|
||||
val m = l - c / 2
|
||||
|
||||
var r = 0f
|
||||
var g = 0f
|
||||
var b = 0f
|
||||
|
||||
when {
|
||||
h < 60f -> {
|
||||
r = c
|
||||
g = x
|
||||
}
|
||||
h < 120f -> {
|
||||
r = x
|
||||
g = c
|
||||
}
|
||||
h < 180f -> {
|
||||
g = c
|
||||
b = x
|
||||
}
|
||||
h < 240f -> {
|
||||
g = x
|
||||
b = c
|
||||
}
|
||||
h < 300f -> {
|
||||
r = x
|
||||
b = c
|
||||
}
|
||||
else -> {
|
||||
r = c
|
||||
b = x
|
||||
}
|
||||
}
|
||||
|
||||
return RgbColor(
|
||||
((r + m) * 255).roundToInt(),
|
||||
((g + m) * 255).roundToInt(),
|
||||
((b + m) * 255).roundToInt()
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.home.room.detail.composer.rainbow
|
||||
|
||||
data class RgbColor(
|
||||
val r: Int,
|
||||
val g: Int,
|
||||
val b: Int
|
||||
)
|
||||
|
||||
fun RgbColor.toDashColor(): String {
|
||||
return listOf(r, g, b)
|
||||
.joinToString(separator = "", prefix = "#") {
|
||||
it.toString(16).padStart(2, '0')
|
||||
}
|
||||
}
|
@ -37,6 +37,9 @@
|
||||
<string name="room_list_sharing_header_recent_rooms">Recent rooms</string>
|
||||
<string name="room_list_sharing_header_other_rooms">Other rooms</string>
|
||||
|
||||
<string name="command_description_rainbow">Sends the given message colored as a rainbow</string>
|
||||
<string name="command_description_rainbow_emote">Sends the given emote colored as a rainbow</string>
|
||||
|
||||
<!-- Title for category in the settings which affect what is displayed in the timeline (ex: show read receipts, etc.) -->
|
||||
<string name="settings_category_timeline">Timeline</string>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user