Skip to content

Commit

Permalink
✨ Gitmoji column (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
patou authored Apr 7, 2024
1 parent 0f42ff1 commit f281980
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 72 deletions.
54 changes: 7 additions & 47 deletions src/main/kotlin/com/github/patou/gitmoji/GitCommitAction.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.github.patou.gitmoji

import com.github.patou.gitmoji.Gitmojis.Companion.insertAt
import com.google.gson.Gson
import com.intellij.ide.TextCopyProvider
import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.PlatformDataKeys
Expand All @@ -30,19 +29,14 @@ import com.intellij.util.ObjectUtils.sentinel
import com.intellij.util.containers.nullize
import com.intellij.util.ui.JBUI.scale
import com.intellij.vcs.commit.message.CommitMessageInspectionProfile.getSubjectRightMargin
import okhttp3.*
import okhttp3.Request.Builder
import java.awt.Point
import java.io.IOException
import javax.swing.JList
import javax.swing.ListSelectionModel

class GitCommitAction : AnAction() {
private val gitmojis = ArrayList<GitmojiData>()

init {
isEnabledInModalContext = true
loadGitmojiFromHTTP()
}

private val regexPattern = ":[a-z0-9_]+:"
Expand All @@ -56,12 +50,13 @@ class GitCommitAction : AnAction() {
val commitMessage = getCommitMessage(actionEvent)
when {
commitMessage != null && project != null -> {
createPopup(project, commitMessage, gitmojis)
createPopup(project, commitMessage, Gitmojis.gitmojis)
.showInBestPositionFor(actionEvent.dataContext)
}
}
}

@Suppress("MissingActionUpdateThread")
private fun createPopup(
project: Project,
commitMessage: CommitMessage,
Expand All @@ -73,7 +68,7 @@ class GitCommitAction : AnAction() {
val previewCommandGroup = sentinel("Preview Commit Message")
val projectInstance = PropertiesComponent.getInstance(project)
val displayEmoji =
projectInstance.getValue(CONFIG_DISPLAY_ICON, Gitmojis.defaultDisplayType()) == "emoji"
projectInstance.getValue(CONFIG_DISPLAY_ICON, defaultDisplayType()) == "emoji"
val currentCommitMessage = commitMessage.editorField.text
val currentOffset = commitMessage.editorField.caretModel.offset

Expand Down Expand Up @@ -172,7 +167,7 @@ class GitCommitAction : AnAction() {
var replaced = false
if (!insertInCarretPosition) {
if (useUnicode) {
for (moji in gitmojis) {
for (moji in Gitmojis.gitmojis) {
if (message.contains("${moji.emoji}$textAfterUnicode")) {
message = message.replaceFirst(
"${moji.emoji}$textAfterUnicode",
Expand Down Expand Up @@ -224,43 +219,8 @@ class GitCommitAction : AnAction() {
private fun getCommitMessage(e: AnActionEvent) =
e.getData(VcsDataKeys.COMMIT_MESSAGE_CONTROL) as? CommitMessage

private fun loadGitmojiFromHTTP() {
val client = OkHttpClient().newBuilder().addInterceptor(SafeGuardInterceptor()).build()
val request: Request = Builder()
.url("https://gitmoji.dev/api/gitmojis")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
loadDefaultGitmoji()
}

override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) loadDefaultGitmoji()
else {
loadGitmoji(response.body!!.string())
}
}
}
})
}

private fun loadDefaultGitmoji() {
javaClass.getResourceAsStream("/gitmojis.json").use { inputStream ->
if (inputStream != null) {
val text = inputStream.bufferedReader().readText()
loadGitmoji(text)
}
}
}

private fun loadGitmoji(text: String) {
Gson().fromJson(text, Gitmojis::class.java).also {
it.gitmojis.forEach { gitmoji ->
gitmojis.add(GitmojiData(gitmoji.code, gitmoji.emoji, gitmoji.description, gitmoji.name))
}
}
GitmojiLocale.loadTranslations()
override fun getActionUpdateThread(): ActionUpdateThread {
return ActionUpdateThread.BGT
}

}
2 changes: 1 addition & 1 deletion src/main/kotlin/com/github/patou/gitmoji/GitMojiConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class GitMojiConfig(private val project: Project) : SearchableConfigurable {
val propertiesComponent = PropertiesComponent.getInstance(project)
val instance = PropertiesComponent.getInstance()

displayEmojiConfig = propertiesComponent.getValue(CONFIG_DISPLAY_ICON, Gitmojis.defaultDisplayType())
displayEmojiConfig = propertiesComponent.getValue(CONFIG_DISPLAY_ICON, defaultDisplayType())
useUnicodeConfig = propertiesComponent.getBoolean(CONFIG_USE_UNICODE, false)
insertInCursorPositionConfig = propertiesComponent.getBoolean(CONFIG_INSERT_IN_CURSOR_POSITION, false)
includeGitMojiDescriptionConfig = propertiesComponent.getBoolean(CONFIG_INCLUDE_GITMOJI_DESCRIPTION, false)
Expand Down
25 changes: 25 additions & 0 deletions src/main/kotlin/com/github/patou/gitmoji/GitmojiCellRenderer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.github.patou.gitmoji

import com.intellij.vcs.log.ui.table.VcsLogGraphTable
import com.intellij.vcs.log.ui.table.VcsLogIconCellRenderer

class GitmojiCellRenderer : VcsLogIconCellRenderer() {
override fun customize(
table: VcsLogGraphTable,
value: Any?,
selected: Boolean,
hasFocus: Boolean,
row: Int,
column: Int
) {
if (value == null || value !is GitmojiData) {
return
}
if (value.name == "anguished") {
append("-")
return
}
icon = value.getIcon()
toolTipText = value.localeDescription
}
}
47 changes: 47 additions & 0 deletions src/main/kotlin/com/github/patou/gitmoji/GitmojiCustomColumn.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.github.patou.gitmoji

import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.project.ProjectManager
import com.intellij.vcs.log.ui.table.GraphTableModel
import com.intellij.vcs.log.ui.table.VcsLogGraphTable
import com.intellij.vcs.log.ui.table.column.VcsLogCustomColumn
import javax.swing.table.TableCellRenderer


@Suppress("UnstableApiUsage")
class GitmojiCustomColumn : VcsLogCustomColumn<GitmojiData> {
override val id: String
get() = "gitmoji"
override val isDynamic: Boolean
get() = true
override val localizedName: String
get() = "Gitmoji"
override val isResizable: Boolean
get() = false

override fun createTableCellRenderer(table: VcsLogGraphTable): TableCellRenderer {
return GitmojiCellRenderer()
}

override fun isEnabledByDefault(): Boolean {
val projectInstance = PropertiesComponent.getInstance(ProjectManager.getInstance().defaultProject)
val useUnicode = projectInstance.getBoolean(CONFIG_USE_UNICODE, false)
return useUnicode
}

override fun getStubValue(model: GraphTableModel): GitmojiData {
return GitmojiData("anguished", "😧", "anguished", "anguished")
}

override fun getValue(model: GraphTableModel, row: Int): GitmojiData? {
model.getCommitMetadata(row).let {
for (moji in Gitmojis.gitmojis) {
if (it.subject.contains(moji.emoji) || it.subject.contains(moji.code)) {
return moji
}
}
}
return null
}

}
26 changes: 26 additions & 0 deletions src/main/kotlin/com/github/patou/gitmoji/GitmojiUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.github.patou.gitmoji

import com.intellij.openapi.util.SystemInfo

fun defaultDisplayType(): String {
return if (SystemInfo.isWindows) "icon" else "emoji"
}

fun insertAt(target: String, position: Int, insert: String): String {
val targetLen = target.length
require(!(position < 0 || position > targetLen)) { "position=$position" }
if (insert.isEmpty()) {
return target
}
if (position == 0) {
return insert + target
} else if (position == targetLen) {
return target + insert
}
val insertLen = insert.length
val buffer = CharArray(targetLen + insertLen)
target.toCharArray(buffer, 0, 0, position)
insert.toCharArray(buffer, position, 0, insertLen)
target.toCharArray(buffer, position + insertLen, position, targetLen)
return String(buffer)
}
68 changes: 45 additions & 23 deletions src/main/kotlin/com/github/patou/gitmoji/Gitmojis.kt
Original file line number Diff line number Diff line change
@@ -1,32 +1,54 @@
package com.github.patou.gitmoji

import com.intellij.openapi.util.SystemInfo
import com.google.gson.Gson
import okhttp3.*
import okhttp3.Request.Builder
import java.io.IOException

class Gitmojis(val gitmojis: List<Gitmoji>) {
class Gitmoji(val emoji: String, val code: String, val description: String, val name: String)
object Gitmojis {
val gitmojis = ArrayList<GitmojiData>()

companion object {
fun defaultDisplayType(): String {
return if (SystemInfo.isWindows) "icon" else "emoji"
}
init {
loadGitmojiFromHTTP()
}

private fun loadGitmojiFromHTTP() {
val client = OkHttpClient().newBuilder().addInterceptor(SafeGuardInterceptor()).build()
val request: Request = Builder()
.url("https://gitmoji.dev/api/gitmojis")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
loadDefaultGitmoji()
}

fun insertAt(target: String, position: Int, insert: String): String {
val targetLen = target.length
require(!(position < 0 || position > targetLen)) { "position=$position" }
if (insert.isEmpty()) {
return target
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) loadDefaultGitmoji()
else {
loadGitmoji(response.body!!.string())
}
}
}
if (position == 0) {
return insert + target
} else if (position == targetLen) {
return target + insert
})
}

private fun loadDefaultGitmoji() {
javaClass.getResourceAsStream("/gitmojis.json").use { inputStream ->
if (inputStream != null) {
val text = inputStream.bufferedReader().readText()
loadGitmoji(text)
}
val insertLen = insert.length
val buffer = CharArray(targetLen + insertLen)
target.toCharArray(buffer, 0, 0, position)
insert.toCharArray(buffer, position, 0, insertLen)
target.toCharArray(buffer, position + insertLen, position, targetLen)
return String(buffer)
}
}
}

private fun loadGitmoji(text: String) {
Gson().fromJson(text, JsonGitmojis::class.java).also {
it.gitmojis.forEach { gitmoji ->
gitmojis.add(GitmojiData(gitmoji.code, gitmoji.emoji, gitmoji.description, gitmoji.name))
}
}
GitmojiLocale.loadTranslations()
}

}
5 changes: 5 additions & 0 deletions src/main/kotlin/com/github/patou/gitmoji/JsonGitmojis.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.github.patou.gitmoji

class JsonGitmojis(val gitmojis: List<JsonGitmoji>) {
class JsonGitmoji(val emoji: String, val code: String, val description: String, val name: String)
}
2 changes: 1 addition & 1 deletion src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
</actions>

<extensions defaultExtensionNs="com.intellij">

<projectConfigurable instance="com.github.patou.gitmoji.GitMojiConfig" groupId="other" key="projectName" bundle="messages.GitmojiBundle"
id="com.github.patou.gitmoji.config"/>
<vcsLogCustomColumn implementation="com.github.patou.gitmoji.GitmojiCustomColumn" />
</extensions>
</idea-plugin>

0 comments on commit f281980

Please sign in to comment.