145 lines
3.3 KiB
Go
145 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/getlantern/systray"
|
|
"github.com/gorilla/websocket"
|
|
"golang.design/x/clipboard"
|
|
)
|
|
|
|
var (
|
|
conn *websocket.Conn
|
|
lastClipboard []byte
|
|
identification string
|
|
isConnected bool
|
|
)
|
|
|
|
func onReady() {
|
|
// Use embedded icon
|
|
systray.SetIcon(EmbeddedIcon)
|
|
|
|
systray.SetTitle("Clipboard Sync")
|
|
systray.SetTooltip("Clipboard synchronization active")
|
|
|
|
mStatus := systray.AddMenuItem("Status: Connecting...", "Connection status")
|
|
mStatus.Disable()
|
|
systray.AddSeparator()
|
|
mQuit := systray.AddMenuItem("Quit", "Quit the application")
|
|
|
|
// Start clipboard monitoring
|
|
go monitorClipboard()
|
|
|
|
// Start client connection
|
|
go startClient(mStatus)
|
|
|
|
// Handle menu interactions
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-mQuit.ClickedCh:
|
|
systray.Quit()
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
func onExit() {
|
|
if conn != nil {
|
|
conn.Close()
|
|
}
|
|
log.Println("Exiting clipboard sync client")
|
|
}
|
|
|
|
func startClient(statusItem *systray.MenuItem) {
|
|
// Use embedded configuration
|
|
identification = EmbeddedIdentification
|
|
server_ip := EmbeddedServerIP
|
|
server_port := EmbeddedServerPort
|
|
server_connection := "ws://" + server_ip + ":" + server_port + "/ws"
|
|
|
|
if identification == "" || server_ip == "" || server_port == "" {
|
|
log.Println("Missing configuration")
|
|
statusItem.SetTitle("Status: Config error")
|
|
return
|
|
}
|
|
|
|
// Connect to the server
|
|
var connectErr error
|
|
conn, _, connectErr = websocket.DefaultDialer.Dial(server_connection, nil)
|
|
if connectErr != nil {
|
|
log.Println("Error connecting to server:", connectErr)
|
|
statusItem.SetTitle("Status: Connection failed")
|
|
return
|
|
}
|
|
|
|
// Send identification to the server
|
|
sendMessage(conn, websocket.TextMessage, []byte(identification))
|
|
|
|
isConnected = true
|
|
statusItem.SetTitle(fmt.Sprintf("Status: Connected (%s)", identification))
|
|
log.Println("Connected to server")
|
|
|
|
// Listen for messages from the server
|
|
for {
|
|
messageType, message, err := conn.ReadMessage()
|
|
if err != nil {
|
|
log.Println("Error reading message:", err)
|
|
isConnected = false
|
|
statusItem.SetTitle("Status: Disconnected")
|
|
return
|
|
}
|
|
handleMessage(messageType, message)
|
|
}
|
|
}
|
|
|
|
func handleMessage(messageType int, message []byte) {
|
|
log.Printf("Received clipboard update: %d bytes", len(message))
|
|
// Update local clipboard tracking to avoid re-sending
|
|
lastClipboard = make([]byte, len(message))
|
|
copy(lastClipboard, message)
|
|
// Write to clipboard
|
|
clipboard.Write(clipboard.FmtText, message)
|
|
log.Println("Clipboard updated")
|
|
}
|
|
|
|
func sendMessage(conn *websocket.Conn, messageType int, message []byte) {
|
|
err := conn.WriteMessage(messageType, message)
|
|
if err != nil {
|
|
log.Println("Error sending message:", err)
|
|
}
|
|
}
|
|
|
|
func monitorClipboard() {
|
|
for {
|
|
if isConnected && conn != nil {
|
|
data := clipboard.Read(clipboard.FmtText)
|
|
|
|
// Check if clipboard has changed
|
|
if len(data) > 0 && !bytes.Equal(data, lastClipboard) {
|
|
log.Printf("Clipboard changed, sending to server: %d bytes", len(data))
|
|
sendMessage(conn, websocket.TextMessage, data)
|
|
lastClipboard = make([]byte, len(data))
|
|
copy(lastClipboard, data)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func getDefaultIcon() []byte {
|
|
return EmbeddedIcon
|
|
}
|
|
|
|
func main() {
|
|
// Initialize clipboard
|
|
clip_err := clipboard.Init()
|
|
if clip_err != nil {
|
|
log.Fatal("Failed to initialize clipboard:", clip_err)
|
|
}
|
|
|
|
// Run systray application
|
|
systray.Run(onReady, onExit)
|
|
}
|