mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-13 09:12:08 -04:00
clipboard: fix reliability of modal/popout
This commit is contained in:
@@ -53,6 +53,7 @@ var (
|
|||||||
clipCopyPasteOnce bool
|
clipCopyPasteOnce bool
|
||||||
clipCopyType string
|
clipCopyType string
|
||||||
clipCopyDownload bool
|
clipCopyDownload bool
|
||||||
|
clipCopyCacheFile string
|
||||||
clipJSONOutput bool
|
clipJSONOutput bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -191,6 +192,8 @@ func init() {
|
|||||||
clipCopyCmd.Flags().BoolVarP(&clipCopyPasteOnce, "paste-once", "o", false, "Exit after first paste")
|
clipCopyCmd.Flags().BoolVarP(&clipCopyPasteOnce, "paste-once", "o", false, "Exit after first paste")
|
||||||
clipCopyCmd.Flags().StringVarP(&clipCopyType, "type", "t", "text/plain;charset=utf-8", "MIME type")
|
clipCopyCmd.Flags().StringVarP(&clipCopyType, "type", "t", "text/plain;charset=utf-8", "MIME type")
|
||||||
clipCopyCmd.Flags().BoolVarP(&clipCopyDownload, "download", "d", false, "Download URL as image and copy as file")
|
clipCopyCmd.Flags().BoolVarP(&clipCopyDownload, "download", "d", false, "Download URL as image and copy as file")
|
||||||
|
clipCopyCmd.Flags().StringVar(&clipCopyCacheFile, "cache-file", "", "")
|
||||||
|
clipCopyCmd.Flags().MarkHidden("cache-file")
|
||||||
|
|
||||||
clipWatchCmd.Flags().BoolVar(&clipJSONOutput, "json", false, "Output as JSON")
|
clipWatchCmd.Flags().BoolVar(&clipJSONOutput, "json", false, "Output as JSON")
|
||||||
clipHistoryCmd.Flags().BoolVar(&clipJSONOutput, "json", false, "Output as JSON")
|
clipHistoryCmd.Flags().BoolVar(&clipJSONOutput, "json", false, "Output as JSON")
|
||||||
@@ -221,6 +224,13 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runClipCopy(cmd *cobra.Command, args []string) {
|
func runClipCopy(cmd *cobra.Command, args []string) {
|
||||||
|
if clipCopyCacheFile != "" {
|
||||||
|
if err := clipboard.ServeCacheFile(clipCopyCacheFile, clipCopyType, clipCopyPasteOnce); err != nil {
|
||||||
|
log.Fatalf("serve cache file: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var data []byte
|
var data []byte
|
||||||
copyFromStdin := false
|
copyFromStdin := false
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package clipboard
|
package clipboard
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@@ -14,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Copy(data []byte, mimeType string) error {
|
func Copy(data []byte, mimeType string) error {
|
||||||
return CopyReader(bytes.NewReader(data), mimeType, false, false)
|
return copyForkCached(data, mimeType, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CopyOpts(data []byte, mimeType string, foreground, pasteOnce bool) error {
|
func CopyOpts(data []byte, mimeType string, foreground, pasteOnce bool) error {
|
||||||
@@ -34,7 +33,7 @@ func CopyOpts(data []byte, mimeType string, foreground, pasteOnce bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}, mimeType, pasteOnce)
|
}, mimeType, pasteOnce)
|
||||||
}
|
}
|
||||||
return CopyReader(bytes.NewReader(data), mimeType, foreground, pasteOnce)
|
return copyForkCached(data, mimeType, pasteOnce)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CopyReader(data io.Reader, mimeType string, foreground, pasteOnce bool) error {
|
func CopyReader(data io.Reader, mimeType string, foreground, pasteOnce bool) error {
|
||||||
@@ -44,6 +43,53 @@ func CopyReader(data io.Reader, mimeType string, foreground, pasteOnce bool) err
|
|||||||
return copyServeReader(data, mimeType, pasteOnce)
|
return copyServeReader(data, mimeType, pasteOnce)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyForkCached(data []byte, mimeType string, pasteOnce bool) error {
|
||||||
|
cacheFile, err := createClipboardCacheFile()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create cache file: %w", err)
|
||||||
|
}
|
||||||
|
cachePath := cacheFile.Name()
|
||||||
|
|
||||||
|
if _, err := cacheFile.Write(data); err != nil {
|
||||||
|
cacheFile.Close()
|
||||||
|
os.Remove(cachePath)
|
||||||
|
return fmt.Errorf("write cache file: %w", err)
|
||||||
|
}
|
||||||
|
if err := cacheFile.Close(); err != nil {
|
||||||
|
os.Remove(cachePath)
|
||||||
|
return fmt.Errorf("close cache file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{os.Args[0], "cl", "copy", "--foreground", "--cache-file", cachePath}
|
||||||
|
if pasteOnce {
|
||||||
|
args = append(args, "--paste-once")
|
||||||
|
}
|
||||||
|
args = append(args, "--type", mimeType)
|
||||||
|
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.Stdin = nil
|
||||||
|
cmd.Stderr = nil
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
||||||
|
cmd.Env = append(os.Environ(), "DMS_CLIP_FORKED=1")
|
||||||
|
|
||||||
|
stdout, err := cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
os.Remove(cachePath)
|
||||||
|
return fmt.Errorf("stdout pipe: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
os.Remove(cachePath)
|
||||||
|
return fmt.Errorf("start: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf [1]byte
|
||||||
|
if _, err := stdout.Read(buf[:]); err != nil {
|
||||||
|
return fmt.Errorf("waiting for clipboard ready: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func copyFork(data io.Reader, mimeType string, pasteOnce bool) error {
|
func copyFork(data io.Reader, mimeType string, pasteOnce bool) error {
|
||||||
args := []string{os.Args[0], "cl", "copy", "--foreground"}
|
args := []string{os.Args[0], "cl", "copy", "--foreground"}
|
||||||
if pasteOnce {
|
if pasteOnce {
|
||||||
@@ -99,6 +145,19 @@ func signalReady() {
|
|||||||
os.Stdout.Write([]byte{1})
|
os.Stdout.Write([]byte{1})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ServeCacheFile(path, mimeType string, pasteOnce bool) error {
|
||||||
|
defer os.Remove(path)
|
||||||
|
return copyServeWithWriter(func(writer io.Writer) error {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("open cache file: %w", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
_, err = io.Copy(writer, f)
|
||||||
|
return err
|
||||||
|
}, mimeType, pasteOnce)
|
||||||
|
}
|
||||||
|
|
||||||
func copyServeReader(data io.Reader, mimeType string, pasteOnce bool) error {
|
func copyServeReader(data io.Reader, mimeType string, pasteOnce bool) error {
|
||||||
cachedData, err := createClipboardCacheFile()
|
cachedData, err := createClipboardCacheFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("No recent clipboard entries found")
|
text: clipboardContent.modal.clipboardAvailable ? I18n.tr("No recent clipboard entries found") : I18n.tr("Connecting to clipboard service…")
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
@@ -181,7 +181,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: I18n.tr("No saved clipboard entries")
|
text: clipboardContent.modal.clipboardAvailable ? I18n.tr("No saved clipboard entries") : I18n.tr("Connecting to clipboard service…")
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
|
|||||||
@@ -60,15 +60,12 @@ DankModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function show() {
|
function show() {
|
||||||
if (!clipboardAvailable) {
|
|
||||||
ToastService.showError(I18n.tr("Clipboard service not available"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
open();
|
open();
|
||||||
activeImageLoads = 0;
|
activeImageLoads = 0;
|
||||||
shouldHaveFocus = true;
|
shouldHaveFocus = true;
|
||||||
ClipboardService.reset();
|
ClipboardService.reset();
|
||||||
ClipboardService.refresh();
|
if (clipboardAvailable)
|
||||||
|
ClipboardService.refresh();
|
||||||
keyboardController.reset();
|
keyboardController.reset();
|
||||||
|
|
||||||
Qt.callLater(function () {
|
Qt.callLater(function () {
|
||||||
|
|||||||
@@ -50,14 +50,11 @@ DankPopout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function show() {
|
function show() {
|
||||||
if (!clipboardAvailable) {
|
|
||||||
ToastService.showError(I18n.tr("Clipboard service not available"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
open();
|
open();
|
||||||
activeImageLoads = 0;
|
activeImageLoads = 0;
|
||||||
ClipboardService.reset();
|
ClipboardService.reset();
|
||||||
ClipboardService.refresh();
|
if (clipboardAvailable)
|
||||||
|
ClipboardService.refresh();
|
||||||
keyboardController.reset();
|
keyboardController.reset();
|
||||||
|
|
||||||
Qt.callLater(function () {
|
Qt.callLater(function () {
|
||||||
@@ -122,10 +119,10 @@ DankPopout {
|
|||||||
onBackgroundClicked: hide()
|
onBackgroundClicked: hide()
|
||||||
|
|
||||||
onShouldBeVisibleChanged: {
|
onShouldBeVisibleChanged: {
|
||||||
if (!shouldBeVisible) {
|
if (!shouldBeVisible)
|
||||||
return;
|
return;
|
||||||
}
|
if (clipboardAvailable)
|
||||||
ClipboardService.refresh();
|
ClipboardService.refresh();
|
||||||
keyboardController.reset();
|
keyboardController.reset();
|
||||||
Qt.callLater(function () {
|
Qt.callLater(function () {
|
||||||
if (contentLoader.item?.searchField) {
|
if (contentLoader.item?.searchField) {
|
||||||
|
|||||||
@@ -255,6 +255,12 @@ Singleton {
|
|||||||
return pinnedEntries.some(pinnedEntry => pinnedEntry.hash === entryHash);
|
return pinnedEntries.some(pinnedEntry => pinnedEntry.hash === entryHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClipboardAvailableChanged: {
|
||||||
|
if (!clipboardAvailable || refCount <= 0)
|
||||||
|
return;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: DMSService
|
target: DMSService
|
||||||
enabled: root.refCount > 0
|
enabled: root.refCount > 0
|
||||||
|
|||||||
Reference in New Issue
Block a user