CopyQ icon indicating copy to clipboard operation
CopyQ copied to clipboard

delete history based on item timestamp

Open monperrus opened this issue 2 years ago • 2 comments

Problem statement Sometimes, I lose some past items because the task at hand is heavy in copy-pasting. On the other hand, sometimes a password stays in my history for too long because of Ctrl-C inactivity.

Describe the solution you'd like Instead of number-based history, it would be great to have an option to delete history based on item timestamps, for example delete items older than 6 hours.

Describe alternatives you've considered I'm not aware of any alternative.

Thanks for the great tool!

monperrus avatar Jul 16 '23 07:07 monperrus

Look at this, I think it can run fine. But to be honest, there hasn't been too much testing.

[Commands]
1\Name=Show/Hide main window
1\Command="
    copyq:
    var showAtCursor = true
    if (visible()) {
        hide()
    } else {
      manual_check_expire()
      showAtCursor? showAt(): show()
    }
        "
1\IsGlobalShortcut=true
1\Enable=false
1\Icon=\xf2d2
1\GlobalShortcut=alt+v
2\Name=Move to Trash
2\Command="
    copyq:
    var trash_tab = '(Trash)'
    var tab_mime = 'application/x-copyq-user-tab'
    var index_mime = 'application/x-copyq-user-index'
    var time_mime = 'application/x-copyq-user-delete-time'

    settings('trash_tab', trash_tab)

    global.moveToTrash = function (source_tab, sel) {
        const rows = sel.rows()
        if (rows.length === 0)
            return 0

        var time = (new Date).toISOString()
        tab(source_tab)
        var trashed = []

        for (var i = 0; i < sel.length; ++i) {
            var item = sel.itemAtIndex(i)
            // Workaround: Convert QByteArray to ByteArray.
            for (var format in item)
                item[format] = ByteArray(item[format])
            item[tab_mime] = source_tab
            item[index_mime] = rows[i]
            item[time_mime] = time
            trashed.push(item)
        }

        tab(trash_tab)
        write(0, trashed)
        tab(source_tab)
        sel.removeAll()

        return 1
    }"
2\IsScript=true
2\Enable=false
2\Icon=\xf1f8
3\Name=Clean the tabs on time
3\Command="
    // Get Recycle Bin Tab Name
    var trash_tab=settings ('trash_tab')

    // Set the tabs to be cleaned and the number of expiration days
    // Delete entries from other tabs to the recycle bin first
    var tabs_times={\"clipboard\": 30 * 24}

    // Delete items directly when they expire in the recycle bin
    tabs_times[`${trash_tab}`] = 60*24

    var time_mime = 'application/x-copyq-user-copy-time'
    var onStartPrevious = global.onStart

    global.onStart = function (manual) {
        manual=='manual' ? '' : onStartPrevious()
        settings('last_check_time', str(new Date()))
        var str_now = dateString('yyyy-MM-dd hh:mm:ss')
        var now = new Date(str_now)
        var de_sel = []
        var count_move = 0
        var count_delete = 0
        for (var t in tabs_times) {
            var days = tabs_times[t]
            tab(t)
            var sel = ItemSelection().selectAll()
            var items = sel.items()
            for (var i = 0; i < sel.length; ++i) {
                if (plugins.itempinned.isPinned(i)) {
                    de_sel.push(i)
                    continue
                }
                var copy_time = new Date(items[i][time_mime])
                if (hoursBetween(now, copy_time) < days) {
                    de_sel.push(i)
                }
            }
            sel.deselectIndexes(de_sel)
            if (sel.length == 0) {
                continue
            } else {
                if (t == trash_tab) {
                    count_delete += sel.length
                    sel.removeAll()
                } else {
                    count_move += sel.length
                    moveToTrash(t, sel)
                }
            }
        }
        if (count_move > 0 || count_delete > 0) {
            popup( count_move + ' entries have been moved to the recycle bin! \\n ' + count_delete + ' entries have been completely deleted!', '', 30000)
        } else {
            popup('No expired entries!')
        }
    }

    // Calculate time difference in hours
    function hoursBetween (now, then) {
        var hours = (now - then) / (1000 * 60 * 60);
        return Math.floor(hours);
    }

    function minimumTime() {
        var min = 999999
        for (var t in tabs_times) {
            var time = tabs_times[t]
            if (min > time)
                min = time
        }
        return min
    }

    global.manual_check_expire = function () {
        var now = new Date()
        var last_check_time = new Date(settings('last_check_time'))
        if (hoursBetween(now, last_check_time)>minimumTime()) {
          onStart('manual')
        }
    }"
3\IsScript=true
3\Enable=false
3\Icon=\xf073
size=3

GFDGIT avatar Jul 23 '23 15:07 GFDGIT

thanks a lot!

monperrus avatar Jul 24 '23 05:07 monperrus