183 lines
4.0 KiB
Lua
183 lines
4.0 KiB
Lua
local proto = require 'proto.proto'
|
||
local util = require 'utility'
|
||
local timer = require "timer"
|
||
local config = require 'config'
|
||
local time = require 'bee.time'
|
||
|
||
local nextToken = util.counter()
|
||
|
||
local m = {}
|
||
|
||
m.map = {}
|
||
|
||
---@class progress
|
||
---@field _uri uri
|
||
---@field _token integer
|
||
local mt = {}
|
||
mt.__index = mt
|
||
mt._title = nil
|
||
mt._message = nil
|
||
mt._removed = false
|
||
mt._clock = 0.0
|
||
mt._delay = 0.0
|
||
mt._percentage = 0.0
|
||
mt._showed = false
|
||
mt._dirty = true
|
||
mt._updated = 0.0
|
||
mt._onCancel = nil
|
||
|
||
---移除进度条
|
||
function mt:remove()
|
||
if self._removed then
|
||
return
|
||
end
|
||
self._removed = true
|
||
local token = self._token
|
||
m.map[token] = nil
|
||
if self._showed then
|
||
self._showed = false
|
||
proto.notify('$/progress', {
|
||
token = token,
|
||
value = {
|
||
kind = 'end',
|
||
}
|
||
})
|
||
--log.info('Remove progress:', token, self._title)
|
||
end
|
||
end
|
||
|
||
function mt:isRemoved()
|
||
return self._removed == true
|
||
end
|
||
|
||
---设置描述
|
||
---@param message string # 描述
|
||
function mt:setMessage(message)
|
||
if self._message == message then
|
||
return
|
||
end
|
||
self._message = message
|
||
self._dirty = true
|
||
self:update()
|
||
end
|
||
|
||
---设置百分比
|
||
---@param per number # 百分比(1-100)
|
||
function mt:setPercentage(per)
|
||
if self._percentage == per then
|
||
return
|
||
end
|
||
self._percentage = math.floor(per)
|
||
self._dirty = true
|
||
self:update()
|
||
end
|
||
|
||
---取消事件
|
||
function mt:onCancel(callback)
|
||
self._onCancel = callback
|
||
self:update()
|
||
end
|
||
|
||
function mt:update()
|
||
if self._removed then
|
||
return
|
||
end
|
||
if not self._dirty then
|
||
return
|
||
end
|
||
if not self._showed
|
||
and self._clock + self._delay <= time.time() then
|
||
self._updated = time.time()
|
||
self._dirty = false
|
||
if not config.get(self._uri, 'Lua.window.progressBar') then
|
||
return
|
||
end
|
||
proto.request('window/workDoneProgress/create', {
|
||
token = self._token,
|
||
})
|
||
proto.notify('$/progress', {
|
||
token = self._token,
|
||
value = {
|
||
kind = 'begin',
|
||
title = self._title,
|
||
cancellable = self._onCancel ~= nil,
|
||
message = self._message,
|
||
percentage = self._percentage,
|
||
}
|
||
})
|
||
self._showed = true
|
||
--log.info('Create progress:', self._token, self._title)
|
||
return
|
||
end
|
||
if not self._showed then
|
||
return
|
||
end
|
||
if not config.get(self._uri, 'Lua.window.progressBar') then
|
||
self:remove()
|
||
return
|
||
end
|
||
if time.time() - self._updated < 50 then
|
||
return
|
||
end
|
||
self._dirty = false
|
||
self._updated = time.time()
|
||
proto.notify('$/progress', {
|
||
token = self._token,
|
||
value = {
|
||
kind = 'report',
|
||
message = self._message,
|
||
percentage = self._percentage,
|
||
}
|
||
})
|
||
--log.info('Report progress:', self._token, self._title, self._message, self._percentage)
|
||
end
|
||
|
||
function mt:__close()
|
||
--log.info('Close progress:', self._token, self._title, self._message)
|
||
self:remove()
|
||
end
|
||
|
||
function m.update()
|
||
---@param prog progress
|
||
for _, prog in pairs(m.map) do
|
||
if prog:isRemoved() then
|
||
goto CONTINUE
|
||
end
|
||
prog:update()
|
||
::CONTINUE::
|
||
end
|
||
end
|
||
|
||
---创建一个进度条
|
||
---@param uri? uri
|
||
---@param title string # 标题
|
||
---@param delay number # 至少经过这么久之后才会显示出来
|
||
function m.create(uri, title, delay)
|
||
local token = nextToken()
|
||
local prog = setmetatable({
|
||
_token = token,
|
||
_title = title,
|
||
_clock = time.time(),
|
||
_delay = delay * 1000,
|
||
_uri = uri,
|
||
}, mt)
|
||
|
||
m.map[token] = prog
|
||
|
||
return prog
|
||
end
|
||
|
||
---取消一个进度条
|
||
function m.cancel(token)
|
||
local prog = m.map[token]
|
||
if not prog then
|
||
return
|
||
end
|
||
xpcall(prog._onCancel, log.error, prog)
|
||
prog:remove()
|
||
end
|
||
|
||
timer.loop(0.1, m.update)
|
||
|
||
return m
|