183 lines
4 KiB
Lua
183 lines
4 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
|