Compare commits

...

10 Commits
1.0.16 ... main

Author SHA1 Message Date
Srar
b499667cbb fix: copy hotkey conflicts with ctrlc 2025-12-12 09:28:29 +08:00
hstyi
1d596e18df chore: disable opengl 2025-07-03 08:48:48 +08:00
hstyi
6f95033009 release: 1.0.17 2025-06-17 09:24:56 +08:00
hstyi
1f08af6575 fix: mixpanel endpoint 2025-06-16 10:16:49 +08:00
hstyi
071a091347 fix: title not showing on Linux 2025-06-16 09:23:10 +08:00
hstyi
ca484618c7 chore: upgrade jdk 21.0.7b1034.51 2025-06-12 17:38:48 +08:00
hstyi
1f68f8a112 fix: text cursor not working (#637) 2025-06-11 10:52:43 +08:00
hstyi
0cd5670bd3 chore: winget.yml 2025-06-11 08:47:47 +08:00
hstyi
8e9c6bcb68 fix: macOS background running (#633) 2025-06-10 17:19:28 +08:00
hstyi
6c1fa0fc53 fix: custom toolbar action missing (#630) 2025-06-10 11:34:31 +08:00
15 changed files with 142 additions and 101 deletions

View File

@@ -11,7 +11,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
# download jdk # download jdk
- run: wget -q -O $RUNNER_TEMP/java_package.tar.gz https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.6-linux-aarch64-b895.91.tar.gz - run: wget -q -O $RUNNER_TEMP/java_package.tar.gz https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.7-linux-aarch64-b1034.51.tar.gz
# appimagetool # appimagetool
- run: sudo apt install libfuse2 - run: sudo apt install libfuse2
@@ -22,7 +22,7 @@ jobs:
with: with:
distribution: 'jdkfile' distribution: 'jdkfile'
jdkFile: ${{ runner.temp }}/java_package.tar.gz jdkFile: ${{ runner.temp }}/java_package.tar.gz
java-version: '21.0.6' java-version: '21.0.7'
architecture: aarch64 architecture: aarch64
- uses: actions/cache@v4 - uses: actions/cache@v4

View File

@@ -11,7 +11,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
# download jdk # download jdk
- run: wget -q -O $RUNNER_TEMP/java_package.tar.gz https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.6-linux-x64-b895.91.tar.gz - run: wget -q -O $RUNNER_TEMP/java_package.tar.gz https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.7-linux-x64-b1034.51.tar.gz
# appimagetool # appimagetool
- run: sudo apt install libfuse2 - run: sudo apt install libfuse2
@@ -22,7 +22,7 @@ jobs:
with: with:
distribution: 'jdkfile' distribution: 'jdkfile'
jdkFile: ${{ runner.temp }}/java_package.tar.gz jdkFile: ${{ runner.temp }}/java_package.tar.gz
java-version: '21.0.6' java-version: '21.0.7'
architecture: x64 architecture: x64
- uses: actions/cache@v4 - uses: actions/cache@v4

View File

@@ -44,7 +44,7 @@ jobs:
xcrun notarytool store-credentials "$STORE_CREDENTIALS" --apple-id "$APPLE_ID" --team-id "$TEAM_ID" --password "$APPLE_PASSWORD" xcrun notarytool store-credentials "$STORE_CREDENTIALS" --apple-id "$APPLE_ID" --team-id "$TEAM_ID" --password "$APPLE_PASSWORD"
# download jdk # download jdk
- run: wget -q -O $RUNNER_TEMP/java_package.tar.gz https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.6-osx-aarch64-b895.91.tar.gz - run: wget -q -O $RUNNER_TEMP/java_package.tar.gz https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.7-osx-aarch64-b1034.51.tar.gz
# install jdk # install jdk
- name: Installing Java - name: Installing Java
@@ -52,7 +52,7 @@ jobs:
with: with:
distribution: 'jdkfile' distribution: 'jdkfile'
jdkFile: ${{ runner.temp }}/java_package.tar.gz jdkFile: ${{ runner.temp }}/java_package.tar.gz
java-version: '21.0.6' java-version: '21.0.7'
architecture: aarch64 architecture: aarch64
- uses: actions/cache@v4 - uses: actions/cache@v4

View File

@@ -44,7 +44,7 @@ jobs:
xcrun notarytool store-credentials "$STORE_CREDENTIALS" --apple-id "$APPLE_ID" --team-id "$TEAM_ID" --password "$APPLE_PASSWORD" xcrun notarytool store-credentials "$STORE_CREDENTIALS" --apple-id "$APPLE_ID" --team-id "$TEAM_ID" --password "$APPLE_PASSWORD"
# download jdk # download jdk
- run: wget -q -O $RUNNER_TEMP/java_package.tar.gz https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.6-osx-x64-b895.91.tar.gz - run: wget -q -O $RUNNER_TEMP/java_package.tar.gz https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.7-osx-x64-b1034.51.tar.gz
# install jdk # install jdk
- name: Installing Java - name: Installing Java
@@ -52,7 +52,7 @@ jobs:
with: with:
distribution: 'jdkfile' distribution: 'jdkfile'
jdkFile: ${{ runner.temp }}/java_package.tar.gz jdkFile: ${{ runner.temp }}/java_package.tar.gz
java-version: '21.0.6' java-version: '21.0.7'
architecture: x64 architecture: x64

View File

@@ -21,9 +21,9 @@ jobs:
- name: Installing Java - name: Installing Java
run: | run: |
curl -s --output ${{ runner.temp }}\java_package.zip -L https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.6-windows-x64-b895.91.zip curl -s --output ${{ runner.temp }}\java_package.zip -L https://cache-redirector.jetbrains.com/intellij-jbr/jbrsdk-21.0.7-windows-x64-b1034.51.zip
unzip -q ${{ runner.temp }}\java_package.zip -d ${{ runner.temp }}\jbr unzip -q ${{ runner.temp }}\java_package.zip -d ${{ runner.temp }}\jbr
echo "JAVA_HOME=${{ runner.temp }}\jbr\jbrsdk-21.0.6-windows-x64-b895.91" >> $env:GITHUB_ENV echo "JAVA_HOME=${{ runner.temp }}\jbr\jbrsdk-21.0.7-windows-x64-b1034.51" >> $env:GITHUB_ENV
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:

View File

@@ -10,5 +10,5 @@ jobs:
if: github.repository == 'TermoraDev/termora' if: github.repository == 'TermoraDev/termora'
with: with:
identifier: TermoraDev.Termora identifier: TermoraDev.Termora
installers-regex: 'x86-64\.exe$' # Only x86-64.exe files installers-regex: '\.exe$'
token: ${{ secrets.WINGET_TOKEN }} token: ${{ secrets.WINGET_TOKEN }}

View File

@@ -21,7 +21,7 @@ plugins {
group = "app.termora" group = "app.termora"
version = "1.0.16" version = "1.0.17"
val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem() val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem()
val arch: ArchitectureInternal = DefaultNativePlatform.getCurrentArchitecture() val arch: ArchitectureInternal = DefaultNativePlatform.getCurrentArchitecture()
@@ -134,16 +134,13 @@ application {
args.add("--add-opens java.desktop/java.awt=ALL-UNNAMED") args.add("--add-opens java.desktop/java.awt=ALL-UNNAMED")
args.add("--add-opens java.desktop/sun.lwawt=ALL-UNNAMED") args.add("--add-opens java.desktop/sun.lwawt=ALL-UNNAMED")
args.add("--add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED") args.add("--add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED")
args.add("--add-exports java.desktop/com.apple.eawt=ALL-UNNAMED")
args.add("-Dsun.java2d.metal=true") args.add("-Dsun.java2d.metal=true")
args.add("-Dapple.awt.application.appearance=system") args.add("-Dapple.awt.application.appearance=system")
} }
args.add("-Dapp-version=${project.version}") args.add("-Dapp-version=${project.version}")
if (os.isLinux) {
args.add("-Dsun.java2d.opengl=true")
}
applicationDefaultJvmArgs = args applicationDefaultJvmArgs = args
mainClass = "app.termora.MainKt" mainClass = "app.termora.MainKt"
} }
@@ -388,10 +385,7 @@ tasks.register<Exec>("jpackage") {
options.add("--add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED") options.add("--add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED")
options.add("-Dapple.awt.application.appearance=system") options.add("-Dapple.awt.application.appearance=system")
options.add("--add-opens java.desktop/sun.lwawt.macosx.concurrent=ALL-UNNAMED") options.add("--add-opens java.desktop/sun.lwawt.macosx.concurrent=ALL-UNNAMED")
} options.add("--add-exports java.desktop/com.apple.eawt=ALL-UNNAMED")
if (os.isLinux) {
options.add("-Dsun.java2d.opengl=true")
} }
val arguments = mutableListOf("${Jvm.current().javaHome}/bin/jpackage") val arguments = mutableListOf("${Jvm.current().javaHome}/bin/jpackage")

View File

@@ -355,7 +355,27 @@ class ApplicationRunner {
.event(getAnalyticsUserID(), "launch", properties) .event(getAnalyticsUserID(), "launch", properties)
val delivery = ClientDelivery() val delivery = ClientDelivery()
delivery.addMessage(message) delivery.addMessage(message)
MixpanelAPI().deliver(delivery, true) val endpoints = listOf(
"https://api-eu.mixpanel.com",
"https://api-in.mixpanel.com",
"https://api.mixpanel.com",
"http://api.mixpanel.com",
)
for (endpoint in endpoints) {
try {
MixpanelAPI(
"$endpoint/track",
"$endpoint/engage",
"$endpoint/groups"
).deliver(delivery, true)
break
} catch (e: Exception) {
if (log.isErrorEnabled) {
log.error(e.message, e)
}
continue
}
}
} catch (e: Exception) { } catch (e: Exception) {
if (log.isErrorEnabled) { if (log.isErrorEnabled) {
log.error(e.message, e) log.error(e.message, e)

View File

@@ -1,10 +1,9 @@
package app.termora package app.termora
import app.termora.Application.ohMyJson import app.termora.Application.ohMyJson
import app.termora.actions.MultipleAction
import com.jgoodies.forms.builder.FormBuilder import com.jgoodies.forms.builder.FormBuilder
import com.jgoodies.forms.layout.FormLayout import com.jgoodies.forms.layout.FormLayout
import kotlinx.serialization.encodeToString
import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils
import org.jdesktop.swingx.action.ActionManager import org.jdesktop.swingx.action.ActionManager
import java.awt.Component import java.awt.Component
@@ -20,6 +19,7 @@ import kotlin.math.min
class CustomizeToolBarDialog( class CustomizeToolBarDialog(
owner: Window, owner: Window,
private val windowScope: WindowScope,
private val toolbar: TermoraToolBar private val toolbar: TermoraToolBar
) : DialogWrapper(owner) { ) : DialogWrapper(owner) {
@@ -147,9 +147,7 @@ class CustomizeToolBarDialog(
leftList.model.removeAllElements() leftList.model.removeAllElements()
rightList.model.removeAllElements() rightList.model.removeAllElements()
for (action in toolbar.getAllActions()) { for (action in toolbar.getAllActions()) {
actionManager.getAction(action.id)?.let { getActionHolder(action.id)?.let { rightList.model.addElement(it) }
rightList.model.addElement(ActionHolder(action.id, it))
}
} }
} }
@@ -259,14 +257,11 @@ class CustomizeToolBarDialog(
override fun windowOpened(e: WindowEvent) { override fun windowOpened(e: WindowEvent) {
removeWindowListener(this) removeWindowListener(this)
for (action in toolbar.getActions()) { for (action in toolbar.getActions()) {
if (action.visible) { if (action.visible) {
actionManager.getAction(action.id) getActionHolder(action.id)?.let { rightList.model.addElement(it) }
?.let { rightList.model.addElement(ActionHolder(action.id, it)) }
} else { } else {
actionManager.getAction(action.id) getActionHolder(action.id)?.let { leftList.model.addElement(it) }
?.let { leftList.model.addElement(ActionHolder(action.id, it)) }
} }
} }
@@ -274,6 +269,17 @@ class CustomizeToolBarDialog(
}) })
} }
private fun getActionHolder(actionId: String): ActionHolder? {
var action = actionManager.getAction(actionId)
if (action == null) {
if (actionId == MultipleAction.MULTIPLE) {
action = MultipleAction.getInstance(windowScope)
}
}
if (action == null) return null
return ActionHolder(actionId, action)
}
private fun resetMoveButtons() { private fun resetMoveButtons() {
val indices = rightList.selectedIndices val indices = rightList.selectedIndices
if (indices.isEmpty()) { if (indices.isEmpty()) {

View File

@@ -423,13 +423,10 @@ class TerminalTabbed(
val popupMenu = FlatPopupMenu() val popupMenu = FlatPopupMenu()
popupMenu.add(I18n.getString("termora.toolbar.customize-toolbar")).addActionListener { popupMenu.add(I18n.getString("termora.toolbar.customize-toolbar")).addActionListener {
val owner = SwingUtilities.getWindowAncestor(this@TerminalTabbed) val owner = SwingUtilities.getWindowAncestor(this@TerminalTabbed)
val dialog = CustomizeToolBarDialog( val dialog = CustomizeToolBarDialog(owner, windowScope, termoraToolBar)
owner,
termoraToolBar
)
dialog.setLocationRelativeTo(owner) dialog.setLocationRelativeTo(owner)
if (dialog.open()) { if (dialog.open()) {
termoraToolBar.rebuild() TermoraToolBar.rebuild()
} }
} }
popupMenu.show(event.component, event.x, event.y) popupMenu.show(event.component, event.x, event.y)

View File

@@ -38,7 +38,7 @@ class TermoraFrame : JFrame(), DataProvider {
private val id = UUID.randomUUID().toString() private val id = UUID.randomUUID().toString()
private val windowScope = ApplicationScope.forWindowScope(this) private val windowScope = ApplicationScope.forWindowScope(this)
private val tabbedPane = MyTabbedPane() private val tabbedPane = MyTabbedPane()
private val toolbar = TermoraToolBar(windowScope, this, tabbedPane) private val toolbar = TermoraToolBar(windowScope, this)
private val terminalTabbed = TerminalTabbed(windowScope, toolbar, tabbedPane) private val terminalTabbed = TerminalTabbed(windowScope, toolbar, tabbedPane)
private val dataProviderSupport = DataProviderSupport() private val dataProviderSupport = DataProviderSupport()
private val welcomePanel = WelcomePanel(windowScope) private val welcomePanel = WelcomePanel(windowScope)
@@ -260,6 +260,10 @@ class TermoraFrame : JFrame(), DataProvider {
private class GlassPane : JComponent() { private class GlassPane : JComponent() {
init {
isFocusable = false
}
override fun paintComponent(g: Graphics) { override fun paintComponent(g: Graphics) {
val img = BackgroundManager.getInstance().getBackgroundImage() ?: return val img = BackgroundManager.getInstance().getBackgroundImage() ?: return
val g2d = g as Graphics2D val g2d = g as Graphics2D
@@ -271,5 +275,9 @@ class TermoraFrame : JFrame(), DataProvider {
g2d.composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER) g2d.composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER)
} }
override fun contains(x: Int, y: Int): Boolean {
return false
}
} }
} }

View File

@@ -43,7 +43,7 @@ class TermoraFrameManager : Disposable {
fun createWindow(): TermoraFrame { fun createWindow(): TermoraFrame {
val frame = TermoraFrame().apply { registerCloseCallback(this) } val frame = TermoraFrame().apply { registerCloseCallback(this) }
frame.title = if (SystemInfo.isLinux) null else Application.getName() frame.title = Application.getName()
frame.defaultCloseOperation = DO_NOTHING_ON_CLOSE frame.defaultCloseOperation = DO_NOTHING_ON_CLOSE
val rectangle = getFrameRectangle() ?: FrameRectangle(-1, -1, 1280, 800, 0) val rectangle = getFrameRectangle() ?: FrameRectangle(-1, -1, 1280, 800, 0)

View File

@@ -5,7 +5,6 @@ import app.termora.actions.*
import app.termora.findeverywhere.FindEverywhereAction import app.termora.findeverywhere.FindEverywhereAction
import app.termora.snippet.SnippetAction import app.termora.snippet.SnippetAction
import com.formdev.flatlaf.FlatClientProperties import com.formdev.flatlaf.FlatClientProperties
import com.formdev.flatlaf.extras.components.FlatTabbedPane
import com.formdev.flatlaf.util.SystemInfo import com.formdev.flatlaf.util.SystemInfo
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils
@@ -26,10 +25,21 @@ data class ToolBarAction(
class TermoraToolBar( class TermoraToolBar(
private val windowScope: WindowScope, private val windowScope: WindowScope,
private val frame: TermoraFrame, private val frame: TermoraFrame,
private val tabbedPane: FlatTabbedPane
) { ) {
companion object {
fun rebuild() {
for (frame in TermoraFrameManager.getInstance().getWindows()) {
val toolbars = SwingUtils.getDescendantsOfClass(MyToolBar::class.java, frame)
for (toolbar in toolbars) {
toolbar.rebuild()
}
}
}
}
private val properties by lazy { Database.getDatabase().properties } private val properties by lazy { Database.getDatabase().properties }
private val toolbar by lazy { MyToolBar().apply { rebuild(this) } } private val toolbar by lazy { MyToolBar().apply { rebuild() } }
fun getJToolBar(): JToolBar { fun getJToolBar(): JToolBar {
@@ -87,11 +97,45 @@ class TermoraToolBar(
return storageActions return storageActions
} }
fun rebuild() { private inner class MyToolBar : JToolBar() {
rebuild(this.toolbar) init {
// 监听窗口大小变动,然后修改边距避开控制按钮
addComponentListener(object : ComponentAdapter() {
override fun componentResized(e: ComponentEvent) {
adjust()
}
})
} }
private fun rebuild(toolbar: JToolBar) { fun adjust() {
if (SystemInfo.isWindows || SystemInfo.isLinux) {
val rectangle =
frame.rootPane.getClientProperty(FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS)
as? Rectangle ?: return
val right = rectangle.width
val toolbar = this@MyToolBar
for (i in 0 until toolbar.componentCount) {
val c = toolbar.getComponent(i)
if (c.name == "spacing") {
if (c.width == right) {
return
}
toolbar.remove(i)
break
}
}
if (right > 0) {
val spacing = Box.createHorizontalStrut(right)
spacing.name = "spacing"
toolbar.add(spacing)
}
}
}
fun rebuild() {
val toolbar: JToolBar = this
val actionManager = ActionManager.getInstance() val actionManager = ActionManager.getInstance()
val actionContainerFactory = ActionContainerFactory(actionManager) val actionContainerFactory = ActionContainerFactory(actionManager)
@@ -143,41 +187,5 @@ class TermoraToolBar(
toolbar.revalidate() toolbar.revalidate()
toolbar.repaint() toolbar.repaint()
} }
private inner class MyToolBar : JToolBar() {
init {
// 监听窗口大小变动,然后修改边距避开控制按钮
addComponentListener(object : ComponentAdapter() {
override fun componentResized(e: ComponentEvent) {
adjust()
}
})
}
fun adjust() {
if (SystemInfo.isWindows || SystemInfo.isLinux) {
val rectangle =
frame.rootPane.getClientProperty(FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_BOUNDS)
as? Rectangle ?: return
val right = rectangle.width
val toolbar = this@MyToolBar
for (i in 0 until toolbar.componentCount) {
val c = toolbar.getComponent(i)
if (c.name == "spacing") {
if (c.width == right) {
return
}
toolbar.remove(i)
break
}
}
if (right > 0) {
val spacing = Box.createHorizontalStrut(right)
spacing.name = "spacing"
toolbar.add(spacing)
}
}
}
} }
} }

View File

@@ -20,6 +20,10 @@ class TerminalCopyAction : AnAction() {
override fun actionPerformed(evt: AnActionEvent) { override fun actionPerformed(evt: AnActionEvent) {
val terminalPanel = evt.getData(DataProviders.TerminalPanel) ?: return val terminalPanel = evt.getData(DataProviders.TerminalPanel) ?: return
val selectionModel = terminalPanel.terminal.getSelectionModel()
if (!selectionModel.hasSelection()) {
return
}
val text = terminalPanel.copy() val text = terminalPanel.copy()
val systemClipboard = terminalPanel.toolkit.systemClipboard val systemClipboard = terminalPanel.toolkit.systemClipboard

View File

@@ -1,5 +1,6 @@
package app.termora.terminal.panel package app.termora.terminal.panel
import app.termora.actions.TerminalCopyAction
import app.termora.keymap.KeyShortcut import app.termora.keymap.KeyShortcut
import app.termora.keymap.KeymapManager import app.termora.keymap.KeymapManager
import app.termora.terminal.ControlCharacters import app.termora.terminal.ControlCharacters
@@ -69,6 +70,7 @@ class TerminalPanelKeyAdapter(
} }
val keyStroke = KeyStroke.getKeyStrokeForEvent(e) val keyStroke = KeyStroke.getKeyStrokeForEvent(e)
val keymapActions = activeKeymap.getActionIds(KeyShortcut(keyStroke))
for (action in terminalPanel.getTerminalActions()) { for (action in terminalPanel.getTerminalActions()) {
if (action.test(keyStroke, e)) { if (action.test(keyStroke, e)) {
action.actionPerformed(e) action.actionPerformed(e)
@@ -100,7 +102,9 @@ class TerminalPanelKeyAdapter(
} }
// 如果命中了全局快捷键,那么不处理 // 如果命中了全局快捷键,那么不处理
if (keyStroke.modifiers != 0 && activeKeymap.getActionIds(KeyShortcut(keyStroke)).isNotEmpty()) { val copyShortcutWithoutSelection =
keymapActions.contains(TerminalCopyAction.COPY) && terminal.getSelectionModel().hasSelection().not()
if (keyStroke.modifiers != 0 && keymapActions.isNotEmpty() && !copyShortcutWithoutSelection) {
return return
} }