clipboard config options + fade text and keyboard input handling
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
import Quickshell.Io
|
||||||
|
|
||||||
|
JsonObject {
|
||||||
|
property bool enabled: true
|
||||||
|
property int maxEntriesShown: 10
|
||||||
|
property Sizes sizes: Sizes {
|
||||||
|
}
|
||||||
|
|
||||||
|
component Sizes: JsonObject {
|
||||||
|
property int itemHeight: 60
|
||||||
|
property int width: 500
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-1
@@ -13,6 +13,7 @@ Singleton {
|
|||||||
property alias appearance: adapter.appearance
|
property alias appearance: adapter.appearance
|
||||||
property alias background: adapter.background
|
property alias background: adapter.background
|
||||||
property alias barConfig: adapter.barConfig
|
property alias barConfig: adapter.barConfig
|
||||||
|
property alias clipboard: adapter.clipboard
|
||||||
property alias colors: adapter.colors
|
property alias colors: adapter.colors
|
||||||
property alias dashboard: adapter.dashboard
|
property alias dashboard: adapter.dashboard
|
||||||
property alias dock: adapter.dock
|
property alias dock: adapter.dock
|
||||||
@@ -116,6 +117,17 @@ Singleton {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function serializeClipboard(): var {
|
||||||
|
return {
|
||||||
|
enabled: clipboard.enabled,
|
||||||
|
maxEntriesShown: clipboard.maxEntriesShown,
|
||||||
|
sizes: {
|
||||||
|
width: clipboard.sizes.width,
|
||||||
|
itemHeight: clipboard.sizes.itemHeight
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function serializeColors(): var {
|
function serializeColors(): var {
|
||||||
return {
|
return {
|
||||||
schemeType: colors.schemeType,
|
schemeType: colors.schemeType,
|
||||||
@@ -143,7 +155,8 @@ Singleton {
|
|||||||
launcher: serializeLauncher(),
|
launcher: serializeLauncher(),
|
||||||
colors: serializeColors(),
|
colors: serializeColors(),
|
||||||
dock: serializeDock(),
|
dock: serializeDock(),
|
||||||
screenshot: serializeScreenshot()
|
screenshot: serializeScreenshot(),
|
||||||
|
clipboard: serializeClipboard()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,6 +460,8 @@ Singleton {
|
|||||||
}
|
}
|
||||||
property BarConfig barConfig: BarConfig {
|
property BarConfig barConfig: BarConfig {
|
||||||
}
|
}
|
||||||
|
property ClipboardConfig clipboard: ClipboardConfig {
|
||||||
|
}
|
||||||
property Colors colors: Colors {
|
property Colors colors: Colors {
|
||||||
}
|
}
|
||||||
property DashboardConfig dashboard: DashboardConfig {
|
property DashboardConfig dashboard: DashboardConfig {
|
||||||
|
|||||||
@@ -17,16 +17,10 @@ Singleton {
|
|||||||
name: Fuzzy.prepare(`${a.replace(/^\s*\S+\s+/, "")}`),
|
name: Fuzzy.prepare(`${a.replace(/^\s*\S+\s+/, "")}`),
|
||||||
entry: a
|
entry: a
|
||||||
}))
|
}))
|
||||||
property string pressPasteCommand: "ydotool key -d 1 29:1 47:1 47:0 29:0"
|
|
||||||
property real scoreThreshold: 0.2
|
property real scoreThreshold: 0.2
|
||||||
|
|
||||||
function copy(entry) {
|
function copy(entry) {
|
||||||
if (root.cliphistBinary.includes("cliphist"))
|
|
||||||
Quickshell.execDetached(["bash", "-c", `printf '${shellSingleQuoteEscape(entry)}' | ${root.cliphistBinary} decode | wl-copy`]);
|
Quickshell.execDetached(["bash", "-c", `printf '${shellSingleQuoteEscape(entry)}' | ${root.cliphistBinary} decode | wl-copy`]);
|
||||||
else {
|
|
||||||
const entryNumber = entry.split("\t")[0];
|
|
||||||
Quickshell.execDetached(["bash", "-c", `${root.cliphistBinary} decode ${entryNumber} | wl-copy`]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteEntry(entry) {
|
function deleteEntry(entry) {
|
||||||
@@ -50,12 +44,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function paste(entry) {
|
function paste(entry) {
|
||||||
if (root.cliphistBinary.includes("cliphist"))
|
|
||||||
Quickshell.execDetached(["bash", "-c", `printf '${shellSingleQuoteEscape(entry)}' | ${root.cliphistBinary} decode | wl-copy && wl-paste`]);
|
Quickshell.execDetached(["bash", "-c", `printf '${shellSingleQuoteEscape(entry)}' | ${root.cliphistBinary} decode | wl-copy && wl-paste`]);
|
||||||
else {
|
|
||||||
const entryNumber = entry.split("\t")[0];
|
|
||||||
Quickshell.execDetached(["bash", "-c", `${root.cliphistBinary} decode ${entryNumber} | wl-copy; ${root.pressPasteCommand}`]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ import qs.Config
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
readonly property int itemHeight: Config.clipboard.sizes.itemHeight
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
implicitHeight: screen.height / 2
|
implicitHeight: search.implicitHeight + entries.anchors.topMargin + ((view.spacing + itemHeight) * Config.clipboard.maxEntriesShown) - view.spacing
|
||||||
implicitWidth: 500
|
implicitWidth: Config.clipboard.sizes.width
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (!ClipHistory.entries.length > 0)
|
if (!ClipHistory.entries.length > 0)
|
||||||
@@ -51,6 +52,13 @@ Item {
|
|||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
color: DynamicColors.palette.m3onSurface
|
color: DynamicColors.palette.m3onSurface
|
||||||
placeholderText: "Search clipboard history..."
|
placeholderText: "Search clipboard history..."
|
||||||
|
|
||||||
|
Keys.onDownPressed: view.incrementCurrentIndex()
|
||||||
|
Keys.onUpPressed: view.decrementCurrentIndex()
|
||||||
|
onAccepted: {
|
||||||
|
ClipHistory.copy(view.currentItem.modelData);
|
||||||
|
root.visibilities.clipboard = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,20 +70,28 @@ Item {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: search.bottom
|
anchors.top: search.bottom
|
||||||
anchors.topMargin: Appearance.spacing.normal
|
anchors.topMargin: Appearance.spacing.normal
|
||||||
radius: Appearance.rounding.normal
|
radius: Appearance.rounding.small
|
||||||
|
|
||||||
ListView {
|
CustomListView {
|
||||||
id: view
|
id: view
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
highlightFollowsCurrentItem: false
|
||||||
|
highlightRangeMode: ListView.ApplyRange
|
||||||
|
preferredHighlightBegin: 0
|
||||||
|
preferredHighlightEnd: height
|
||||||
spacing: Appearance.spacing.normal
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
|
CustomScrollBar.vertical: CustomScrollBar {
|
||||||
|
flickable: view
|
||||||
|
}
|
||||||
delegate: RowLayout {
|
delegate: RowLayout {
|
||||||
id: clipItem
|
id: clipItem
|
||||||
|
|
||||||
required property string modelData
|
required property string modelData
|
||||||
|
|
||||||
height: 50
|
height: root.itemHeight
|
||||||
|
spacing: Appearance.spacing.small
|
||||||
width: view.width
|
width: view.width
|
||||||
|
|
||||||
CustomClippingRect {
|
CustomClippingRect {
|
||||||
@@ -83,8 +99,6 @@ Item {
|
|||||||
|
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
// Layout.preferredWidth: implicitWidth + (textLayer.pressed ? 18 : 0)
|
|
||||||
// implicitWidth: 250
|
|
||||||
radius: textLayer.pressed ? (Appearance.rounding.small / 2) : Appearance.rounding.small
|
radius: textLayer.pressed ? (Appearance.rounding.small / 2) : Appearance.rounding.small
|
||||||
|
|
||||||
Behavior on Layout.preferredWidth {
|
Behavior on Layout.preferredWidth {
|
||||||
@@ -98,6 +112,16 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: textWrapper
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
layer.enabled: true
|
||||||
|
|
||||||
|
layer.effect: OpacityMask {
|
||||||
|
maskSource: fadeMask
|
||||||
|
}
|
||||||
|
|
||||||
CustomText {
|
CustomText {
|
||||||
id: text
|
id: text
|
||||||
|
|
||||||
@@ -107,6 +131,29 @@ Item {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
text: clipItem.modelData
|
text: clipItem.modelData
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: fadeMask
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
layer.enabled: true
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
gradient: Gradient {
|
||||||
|
orientation: Gradient.Horizontal
|
||||||
|
|
||||||
|
GradientStop {
|
||||||
|
color: Qt.rgba(1, 1, 1, 1.0)
|
||||||
|
position: 0.85
|
||||||
|
}
|
||||||
|
|
||||||
|
GradientStop {
|
||||||
|
color: Qt.rgba(1, 1, 1, 0)
|
||||||
|
position: 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StateLayer {
|
StateLayer {
|
||||||
id: textLayer
|
id: textLayer
|
||||||
@@ -116,17 +163,17 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IconButton {
|
IconButton {
|
||||||
|
Layout.bottomMargin: Appearance.padding.normal
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.margins: Appearance.padding.smallest
|
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
|
Layout.topMargin: Appearance.padding.normal
|
||||||
icon: "content_copy"
|
icon: "content_copy"
|
||||||
isToggle: false
|
isToggle: false
|
||||||
// implicitWidth: 30
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IconButton {
|
IconButton {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.margins: Appearance.padding.smallest
|
Layout.margins: Appearance.padding.normal
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
icon: "delete"
|
icon: "delete"
|
||||||
inactiveColor: Qt.alpha(DynamicColors.palette.m3error, 0.8)
|
inactiveColor: Qt.alpha(DynamicColors.palette.m3error, 0.8)
|
||||||
@@ -134,15 +181,24 @@ Item {
|
|||||||
isToggle: false
|
isToggle: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
model: ScriptModel {
|
highlight: CustomRect {
|
||||||
values: {
|
color: DynamicColors.palette.m3onSurface
|
||||||
const entries = ClipHistory.entries;
|
implicitHeight: view.currentItem?.height ?? 0
|
||||||
const search = searchField.text;
|
implicitWidth: view.width
|
||||||
var regex = new RegExp(search, "i");
|
opacity: 0.08
|
||||||
|
radius: Appearance.rounding.small
|
||||||
|
y: view.currentItem?.y ?? 0
|
||||||
|
|
||||||
return entries.filter(n => regex.test(n));
|
Behavior on y {
|
||||||
|
Anim {
|
||||||
|
duration: Appearance.anim.durations.small
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
model: ScriptModel {
|
||||||
|
values: ClipHistory.fuzzyQuery(searchField.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user