initial commit
This commit is contained in:
1758
Core/UI/AuctionUI/Auctioning.lua
Normal file
1758
Core/UI/AuctionUI/Auctioning.lua
Normal file
File diff suppressed because it is too large
Load Diff
441
Core/UI/AuctionUI/BuyUtil.lua
Normal file
441
Core/UI/AuctionUI/BuyUtil.lua
Normal file
@@ -0,0 +1,441 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster --
|
||||
-- https://tradeskillmaster.com --
|
||||
-- All Rights Reserved - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local _, TSM = ...
|
||||
local BuyUtil = TSM.UI.AuctionUI:NewPackage("BuyUtil")
|
||||
local L = TSM.Include("Locale").GetTable()
|
||||
local Money = TSM.Include("Util.Money")
|
||||
local Log = TSM.Include("Util.Log")
|
||||
local Math = TSM.Include("Util.Math")
|
||||
local Theme = TSM.Include("Util.Theme")
|
||||
local ItemInfo = TSM.Include("Service.ItemInfo")
|
||||
local CustomPrice = TSM.Include("Service.CustomPrice")
|
||||
local UIElements = TSM.Include("UI.UIElements")
|
||||
local private = {
|
||||
totalBuyout = nil,
|
||||
isBuy = nil,
|
||||
auctionScan = nil,
|
||||
subRow = nil,
|
||||
index = nil,
|
||||
noSeller = nil,
|
||||
baseFrame = nil,
|
||||
dialogFrame = nil,
|
||||
future = nil,
|
||||
prepareQuantity = nil,
|
||||
prepareSuccess = false,
|
||||
marketValueFunc = nil,
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Module Functions
|
||||
-- ============================================================================
|
||||
|
||||
function BuyUtil.ShowConfirmation(baseFrame, subRow, isBuy, auctionNum, numFound, maxQuantity, callback, auctionScan, index, noSeller, marketValueFunc)
|
||||
auctionNum = min(auctionNum, numFound)
|
||||
local buyout = subRow:GetBuyouts()
|
||||
if not isBuy then
|
||||
buyout = subRow:GetRequiredBid(subRow)
|
||||
end
|
||||
local quantity = subRow:GetQuantities()
|
||||
local itemString = subRow:GetItemString()
|
||||
local _, _, _, isHighBidder = subRow:GetBidInfo()
|
||||
local isCommodity = not TSM.IsWowClassic() and subRow:IsCommodity()
|
||||
local shouldConfirm = false
|
||||
if isCommodity then
|
||||
shouldConfirm = true
|
||||
elseif isBuy and isHighBidder then
|
||||
shouldConfirm = true
|
||||
elseif TSM.db.global.shoppingOptions.buyoutConfirm then
|
||||
shouldConfirm = ceil(buyout / quantity) >= (CustomPrice.GetValue(TSM.db.global.shoppingOptions.buyoutAlertSource, itemString) or 0)
|
||||
end
|
||||
if not shouldConfirm then
|
||||
return false
|
||||
end
|
||||
|
||||
baseFrame = baseFrame:GetBaseElement()
|
||||
private.isBuy = isBuy
|
||||
private.auctionScan = auctionScan
|
||||
private.subRow = subRow
|
||||
private.index = index
|
||||
private.noSeller = noSeller
|
||||
private.baseFrame = baseFrame
|
||||
private.marketValueFunc = marketValueFunc
|
||||
if private.dialogFrame then
|
||||
return true
|
||||
end
|
||||
|
||||
local defaultQuantity = isCommodity and numFound or 1
|
||||
assert(not isCommodity or isBuy)
|
||||
|
||||
local displayItemBuyout, displayTotalBuyout = nil, nil
|
||||
if isCommodity then
|
||||
displayTotalBuyout = private.CommodityResultsByQuantity(itemString, defaultQuantity)
|
||||
displayItemBuyout = Math.Ceil(displayTotalBuyout / defaultQuantity, COPPER_PER_SILVER)
|
||||
else
|
||||
displayItemBuyout = ceil(buyout / quantity)
|
||||
displayTotalBuyout = TSM.IsWowClassic() and buyout or ceil(buyout / quantity)
|
||||
end
|
||||
|
||||
private.dialogFrame = UIElements.New("Frame", "frame")
|
||||
:SetLayout("VERTICAL")
|
||||
:SetSize(isCommodity and 600 or 326, isCommodity and 272 or 262)
|
||||
:SetPadding(12)
|
||||
:AddAnchor("CENTER")
|
||||
:SetContext(callback)
|
||||
:SetMouseEnabled(true)
|
||||
:SetBackgroundColor("FRAME_BG", true)
|
||||
:AddChild(UIElements.New("Frame", "header")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(24)
|
||||
:SetMargin(0, 0, -4, 10)
|
||||
:AddChild(UIElements.New("Spacer", "spacer")
|
||||
:SetWidth(20)
|
||||
)
|
||||
:AddChild(UIElements.New("Text", "title")
|
||||
:SetJustifyH("CENTER")
|
||||
:SetFont("BODY_BODY1_BOLD")
|
||||
:SetText(isCommodity and L["Order Confirmation"] or L["Buyout"])
|
||||
)
|
||||
:AddChild(UIElements.New("Button", "closeBtn")
|
||||
:SetMargin(0, -4, 0, 0)
|
||||
:SetBackgroundAndSize("iconPack.24x24/Close/Default")
|
||||
:SetScript("OnClick", private.BuyoutConfirmCloseBtnOnClick)
|
||||
)
|
||||
)
|
||||
:AddChild(UIElements.New("Frame", "content")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:AddChild(UIElements.New("Frame", "left")
|
||||
:SetLayout("VERTICAL")
|
||||
:AddChild(UIElements.New("Frame", "item")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetPadding(6)
|
||||
:SetMargin(0, 0, 0, 16)
|
||||
:SetBackgroundColor("PRIMARY_BG_ALT", true)
|
||||
:AddChild(UIElements.New("Button", "icon")
|
||||
:SetSize(36, 36)
|
||||
:SetMargin(0, 8, 0, 0)
|
||||
:SetBackground(ItemInfo.GetTexture(itemString))
|
||||
:SetTooltip(itemString)
|
||||
)
|
||||
:AddChild(UIElements.New("Text", "name")
|
||||
:SetHeight(36)
|
||||
:SetFont("ITEM_BODY1")
|
||||
:SetText(TSM.UI.GetColoredItemName(itemString))
|
||||
)
|
||||
)
|
||||
:AddChildIf(isCommodity, UIElements.New("Frame", "quantity")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(24)
|
||||
:AddChild(UIElements.New("Text", "desc")
|
||||
:SetFont("BODY_BODY2")
|
||||
:SetText(L["Quantity"]..":")
|
||||
)
|
||||
:AddChild(UIElements.New("Input", "input")
|
||||
:SetWidth(140)
|
||||
:SetJustifyH("RIGHT")
|
||||
:SetBackgroundColor("PRIMARY_BG_ALT")
|
||||
:SetValidateFunc("NUMBER", "1:"..maxQuantity)
|
||||
:SetValue(tostring(defaultQuantity))
|
||||
:SetContext(maxQuantity)
|
||||
:SetScript("OnValueChanged", private.InputQtyOnValueChanged)
|
||||
)
|
||||
)
|
||||
:AddChildIf(not isCommodity, UIElements.New("Frame", "stacks")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(20)
|
||||
:SetMargin(0, 0, 0, 10)
|
||||
:AddChild(UIElements.New("Text", "desc")
|
||||
:SetWidth("AUTO")
|
||||
:SetFont("BODY_BODY2")
|
||||
:SetText(isBuy and L["Purchasing Auction"]..":" or L["Bidding Auction"]..":")
|
||||
)
|
||||
:AddChild(UIElements.New("Text", "number")
|
||||
:SetJustifyH("RIGHT")
|
||||
:SetFont("TABLE_TABLE1")
|
||||
:SetText(auctionNum.."/"..numFound)
|
||||
)
|
||||
)
|
||||
:AddChild(UIElements.New("Spacer", "spacer"))
|
||||
:AddChild(UIElements.New("Frame", "price")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(20)
|
||||
:SetMargin(0, 0, 0, 10)
|
||||
:AddChild(UIElements.New("Text", "desc")
|
||||
:SetWidth("AUTO")
|
||||
:SetFont("BODY_BODY2")
|
||||
:SetText(L["Unit Price"]..":")
|
||||
)
|
||||
:AddChild(UIElements.New("Text", "money")
|
||||
:SetJustifyH("RIGHT")
|
||||
:SetFont("TABLE_TABLE1")
|
||||
:SetContext(displayItemBuyout)
|
||||
:SetText(private.GetUnitPriceMoneyStr(displayItemBuyout))
|
||||
)
|
||||
)
|
||||
:AddChild(UIElements.New("Frame", "total")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(20)
|
||||
:SetMargin(0, 0, 0, 10)
|
||||
:AddChild(UIElements.New("Text", "desc")
|
||||
:SetWidth("AUTO")
|
||||
:SetFont("BODY_BODY2")
|
||||
:SetText(L["Total Price"]..":")
|
||||
)
|
||||
:AddChild(UIElements.New("Text", "money")
|
||||
:SetJustifyH("RIGHT")
|
||||
:SetFont("TABLE_TABLE1")
|
||||
:SetText(Money.ToString(displayTotalBuyout, nil, "OPT_83_NO_COPPER"))
|
||||
)
|
||||
)
|
||||
:AddChild(UIElements.New("Text", "warning")
|
||||
:SetHeight(20)
|
||||
:SetMargin(0, 0, 0, 10)
|
||||
:SetFont("BODY_BODY3")
|
||||
:SetJustifyH("CENTER")
|
||||
:SetTextColor(Theme.GetFeedbackColor("YELLOW"))
|
||||
:SetText("")
|
||||
)
|
||||
:AddChild(UIElements.NewNamed("ActionButton", "confirmBtn", "TSMBidBuyConfirmBtn")
|
||||
:SetHeight(24)
|
||||
:SetText(isCommodity and L["Buy Commodity"] or (isBuy and L["Buy Auction"] or L["Bid Auction"]))
|
||||
:SetContext(not isCommodity and quantity or nil)
|
||||
:SetDisabled(private.future and true or false)
|
||||
:SetScript("OnClick", private.ConfirmBtnOnClick)
|
||||
)
|
||||
)
|
||||
:AddChildIf(isCommodity, UIElements.New("Frame", "item")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetWidth(266)
|
||||
:SetMargin(12, 0, 0, 0)
|
||||
:SetPadding(4, 4, 8, 8)
|
||||
:SetBackgroundColor("PRIMARY_BG_ALT", true)
|
||||
:AddChild(UIElements.New("CommodityList", "items")
|
||||
:SetBackgroundColor("PRIMARY_BG_ALT")
|
||||
:SetData(subRow:GetResultRow())
|
||||
:SetMarketValueFunction(marketValueFunc)
|
||||
:SetAlertThreshold(TSM.db.global.shoppingOptions.buyoutConfirm and (CustomPrice.GetValue(TSM.db.global.shoppingOptions.buyoutAlertSource, itemString) or 0) or nil)
|
||||
:SelectQuantity(defaultQuantity)
|
||||
:SetScript("OnRowClick", private.CommodityOnRowClick)
|
||||
)
|
||||
)
|
||||
)
|
||||
:SetScript("OnHide", private.DialogOnHide)
|
||||
baseFrame:ShowDialogFrame(private.dialogFrame)
|
||||
private.prepareQuantity = nil
|
||||
private.Prepare(defaultQuantity)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Private Helper Functions
|
||||
-- ============================================================================
|
||||
|
||||
function private.DialogOnHide()
|
||||
if private.future then
|
||||
private.future:Cancel()
|
||||
private.future = nil
|
||||
end
|
||||
private.baseFrame = nil
|
||||
private.dialogFrame = nil
|
||||
private.isBuy = nil
|
||||
private.auctionScan = nil
|
||||
private.subRow = nil
|
||||
private.index = nil
|
||||
private.noSeller = nil
|
||||
end
|
||||
|
||||
function private.BuyoutConfirmCloseBtnOnClick(button)
|
||||
button:GetBaseElement():HideDialog()
|
||||
end
|
||||
|
||||
function private.EnableFutureOnDone()
|
||||
local result = private.future:GetValue()
|
||||
private.future = nil
|
||||
if not result or result ~= (private.subRow:IsCommodity() and private.totalBuyout or select(2, private.subRow:GetBuyouts())) then
|
||||
-- the unit price changed
|
||||
Log.PrintUser(L["Failed to buy auction."])
|
||||
private.baseFrame:HideDialog()
|
||||
return
|
||||
end
|
||||
local input = private.dialogFrame:GetElement("content.left.quantity.input")
|
||||
private.prepareSuccess = tonumber(input:GetValue()) == private.prepareQuantity
|
||||
private.UpdateConfirmButton()
|
||||
end
|
||||
|
||||
function private.GetUnitPriceMoneyStr(itemBuyout)
|
||||
local priceStr = Money.ToString(itemBuyout, nil, "OPT_83_NO_COPPER")
|
||||
local marketValueStr = nil
|
||||
local marketValue = private.marketValueFunc(private.subRow)
|
||||
local pct = marketValue and marketValue > 0 and itemBuyout > 0 and Math.Round(100 * itemBuyout / marketValue) or nil
|
||||
if pct then
|
||||
local pctColor = Theme.GetAuctionPercentColor(pct)
|
||||
if pct > 999 then
|
||||
marketValueStr = pctColor:ColorText(">999%")
|
||||
else
|
||||
marketValueStr = pctColor:ColorText(pct.."%")
|
||||
end
|
||||
else
|
||||
marketValueStr = "---"
|
||||
end
|
||||
return format("%s (%s)", priceStr, marketValueStr)
|
||||
end
|
||||
|
||||
function private.CommodityResultsByQuantity(itemString, quantity)
|
||||
local remainingQuantity = quantity
|
||||
local totalPrice, maxPrice = 0, 0
|
||||
for _, query in private.auctionScan:QueryIterator() do
|
||||
for _, subRow in query:ItemSubRowIterator(itemString) do
|
||||
if remainingQuantity > 0 then
|
||||
local _, itemBuyout = subRow:GetBuyouts()
|
||||
local _, numOwnerItems = subRow:GetOwnerInfo()
|
||||
local quantityAvailable = subRow:GetQuantities() - numOwnerItems
|
||||
local quantityToBuy = min(quantityAvailable, remainingQuantity)
|
||||
totalPrice = totalPrice + (itemBuyout * quantityToBuy)
|
||||
remainingQuantity = remainingQuantity - quantityToBuy
|
||||
maxPrice = max(maxPrice, itemBuyout)
|
||||
end
|
||||
end
|
||||
end
|
||||
return totalPrice, maxPrice
|
||||
end
|
||||
|
||||
function private.InputQtyOnValueChanged(input, noListUpdate)
|
||||
local quantity = tonumber(input:GetValue())
|
||||
input:SetValue(quantity)
|
||||
local totalBuyout = private.subRow:IsCommodity() and private.CommodityResultsByQuantity(private.subRow:GetItemString(), quantity) or input:GetElement("__parent.__parent.price.money"):GetContext() * quantity
|
||||
local totalQuantity = quantity
|
||||
local itemBuyout = totalQuantity > 0 and Math.Ceil(totalBuyout / totalQuantity, COPPER_PER_SILVER) or 0
|
||||
input:GetElement("__parent.__parent.price.money")
|
||||
:SetContext(itemBuyout)
|
||||
:SetText(private.GetUnitPriceMoneyStr(itemBuyout))
|
||||
:Draw()
|
||||
input:GetElement("__parent.__parent.total.money")
|
||||
:SetText(Money.ToString(totalBuyout, nil, "OPT_83_NO_COPPER"))
|
||||
:Draw()
|
||||
if not noListUpdate then
|
||||
input:GetElement("__parent.__parent.__parent.item.items")
|
||||
:SelectQuantity(quantity)
|
||||
end
|
||||
if quantity ~= private.prepareQuantity then
|
||||
private.prepareSuccess = false
|
||||
private.prepareQuantity = nil
|
||||
end
|
||||
private.UpdateConfirmButton()
|
||||
end
|
||||
|
||||
function private.CommodityOnRowClick(list, index)
|
||||
local input = list:GetElement("__parent.__parent.left.quantity.input")
|
||||
input:SetValue(list:GetTotalQuantity(index))
|
||||
:Draw()
|
||||
private.Prepare(tonumber(input:GetValue()))
|
||||
private.InputQtyOnValueChanged(input, true)
|
||||
end
|
||||
|
||||
function private.ConfirmBtnOnClick(button)
|
||||
local inputQuantity = nil
|
||||
if not TSM.IsWowClassic() and private.subRow:IsCommodity() then
|
||||
local input = private.dialogFrame:GetElement("content.left.quantity.input")
|
||||
inputQuantity = tonumber(input:GetValue())
|
||||
if not private.prepareSuccess and not TSM.IsWowClassic() then
|
||||
-- this is a prepare click
|
||||
private.Prepare(inputQuantity)
|
||||
return
|
||||
end
|
||||
assert(private.prepareQuantity == inputQuantity)
|
||||
end
|
||||
|
||||
local isBuy = private.isBuy
|
||||
local callbackQuantity = button:GetContext()
|
||||
if callbackQuantity == nil then
|
||||
assert(inputQuantity)
|
||||
callbackQuantity = inputQuantity
|
||||
end
|
||||
local callback = button:GetElement("__parent.__parent.__parent"):GetContext()
|
||||
button:GetBaseElement():HideDialog()
|
||||
callback(isBuy, callbackQuantity)
|
||||
end
|
||||
|
||||
function private.UpdateConfirmButton()
|
||||
local confirmBtn = private.dialogFrame:GetElement("content.left.confirmBtn")
|
||||
local text, disabled, requireManualClick = nil, false, false
|
||||
if not TSM.IsWowClassic() and private.subRow:IsCommodity() then
|
||||
local input = confirmBtn:GetElement("__parent.quantity.input")
|
||||
local inputQuantity = tonumber(input:GetValue())
|
||||
local minQuantity = 1
|
||||
local maxQuantity = confirmBtn:GetElement("__parent.quantity.input"):GetContext()
|
||||
local itemString = private.subRow:GetItemString()
|
||||
local totalCost, maxCost = private.CommodityResultsByQuantity(itemString, inputQuantity)
|
||||
local alertThreshold = TSM.db.global.shoppingOptions.buyoutConfirm and (CustomPrice.GetValue(TSM.db.global.shoppingOptions.buyoutAlertSource, itemString) or 0) or math.huge
|
||||
if maxCost >= alertThreshold then
|
||||
requireManualClick = true
|
||||
confirmBtn:GetElement("__parent.warning")
|
||||
:SetText(L["Contains auctions above your alert threshold!"])
|
||||
:Draw()
|
||||
else
|
||||
confirmBtn:GetElement("__parent.warning")
|
||||
:SetText("")
|
||||
:Draw()
|
||||
end
|
||||
|
||||
if GetMoney() < totalCost then
|
||||
text = L["Not Enough Money"]
|
||||
disabled = true
|
||||
elseif totalCost <= 0 or inputQuantity < minQuantity or inputQuantity > maxQuantity then
|
||||
text = L["Invalid Quantity"]
|
||||
disabled = true
|
||||
elseif private.prepareSuccess or TSM.IsWowClassic() then
|
||||
text = L["Buy Commodity"]
|
||||
disabled = false
|
||||
elseif private.prepareQuantity then
|
||||
text = L["Preparing..."]
|
||||
disabled = true
|
||||
else
|
||||
text = private.isBuy and L["Prepare Buy"] or L["Prepare Bid"]
|
||||
disabled = false
|
||||
end
|
||||
else
|
||||
if GetMoney() < confirmBtn:GetElement("__parent.price.money"):GetContext() then
|
||||
text = L["Not Enough Money"]
|
||||
disabled = true
|
||||
else
|
||||
text = private.isBuy and L["Buy Auction"] or L["Bid Auction"]
|
||||
disabled = false
|
||||
end
|
||||
end
|
||||
confirmBtn:SetText(text)
|
||||
:SetDisabled(disabled)
|
||||
:SetRequireManualClick(requireManualClick)
|
||||
:Draw()
|
||||
end
|
||||
|
||||
function private.Prepare(quantity)
|
||||
if quantity == private.prepareQuantity then
|
||||
return
|
||||
end
|
||||
if private.future then
|
||||
private.future:Cancel()
|
||||
private.future = nil
|
||||
end
|
||||
private.prepareQuantity = quantity
|
||||
private.prepareSuccess = false
|
||||
local totalBuyout = not TSM.IsWowClassic() and private.subRow:IsCommodity() and private.CommodityResultsByQuantity(private.subRow:GetItemString(), quantity) or (select(2, private.subRow:GetBuyouts()))
|
||||
local totalQuantity = quantity
|
||||
private.totalBuyout = totalBuyout
|
||||
local itemBuyout = totalQuantity > 0 and Math.Ceil(totalBuyout / totalQuantity, COPPER_PER_SILVER)
|
||||
local result, future = private.auctionScan:PrepareForBidOrBuyout(private.index, private.subRow, private.noSeller, quantity, itemBuyout)
|
||||
if not result then
|
||||
private.prepareQuantity = nil
|
||||
return
|
||||
elseif future then
|
||||
private.future = future
|
||||
future:SetScript("OnDone", private.EnableFutureOnDone)
|
||||
end
|
||||
private.UpdateConfirmButton()
|
||||
end
|
||||
271
Core/UI/AuctionUI/Core.lua
Normal file
271
Core/UI/AuctionUI/Core.lua
Normal file
@@ -0,0 +1,271 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster --
|
||||
-- https://tradeskillmaster.com --
|
||||
-- All Rights Reserved - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local _, TSM = ...
|
||||
local AuctionUI = TSM.UI:NewPackage("AuctionUI")
|
||||
local L = TSM.Include("Locale").GetTable()
|
||||
local Delay = TSM.Include("Util.Delay")
|
||||
local Event = TSM.Include("Util.Event")
|
||||
local Log = TSM.Include("Util.Log")
|
||||
local ScriptWrapper = TSM.Include("Util.ScriptWrapper")
|
||||
local Settings = TSM.Include("Service.Settings")
|
||||
local ItemLinked = TSM.Include("Service.ItemLinked")
|
||||
local UIElements = TSM.Include("UI.UIElements")
|
||||
local private = {
|
||||
settings = nil,
|
||||
topLevelPages = {},
|
||||
frame = nil,
|
||||
hasShown = false,
|
||||
isSwitching = false,
|
||||
scanningPage = nil,
|
||||
updateCallbacks = {},
|
||||
defaultFrame = nil,
|
||||
}
|
||||
local MIN_FRAME_SIZE = { width = 750, height = 450 }
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Module Functions
|
||||
-- ============================================================================
|
||||
|
||||
function AuctionUI.OnInitialize()
|
||||
private.settings = Settings.NewView()
|
||||
:AddKey("global", "auctionUIContext", "showDefault")
|
||||
:AddKey("global", "auctionUIContext", "frame")
|
||||
UIParent:UnregisterEvent("AUCTION_HOUSE_SHOW")
|
||||
Event.Register("AUCTION_HOUSE_SHOW", private.AuctionFrameInit)
|
||||
Event.Register("AUCTION_HOUSE_CLOSED", private.HideAuctionFrame)
|
||||
if TSM.IsWowClassic() then
|
||||
Delay.AfterTime(1, function() LoadAddOn("Blizzard_AuctionUI") end)
|
||||
else
|
||||
Delay.AfterTime(1, function() LoadAddOn("Blizzard_AuctionHouseUI") end)
|
||||
end
|
||||
ItemLinked.RegisterCallback(private.ItemLinkedCallback)
|
||||
end
|
||||
|
||||
function AuctionUI.OnDisable()
|
||||
if private.frame then
|
||||
-- hide the frame
|
||||
private.frame:Hide()
|
||||
assert(not private.frame)
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionUI.RegisterTopLevelPage(name, callback, itemLinkedHandler)
|
||||
tinsert(private.topLevelPages, { name = name, callback = callback, itemLinkedHandler = itemLinkedHandler })
|
||||
end
|
||||
|
||||
function AuctionUI.StartingScan(pageName)
|
||||
if private.scanningPage and private.scanningPage ~= pageName then
|
||||
Log.PrintfUser(L["A scan is already in progress. Please stop that scan before starting another one."])
|
||||
return false
|
||||
end
|
||||
private.scanningPage = pageName
|
||||
Log.Info("Starting scan %s", pageName)
|
||||
if private.frame then
|
||||
private.frame:SetPulsingNavButton(private.scanningPage)
|
||||
end
|
||||
for _, callback in ipairs(private.updateCallbacks) do
|
||||
callback()
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function AuctionUI.EndedScan(pageName)
|
||||
if private.scanningPage == pageName then
|
||||
Log.Info("Ended scan %s", pageName)
|
||||
private.scanningPage = nil
|
||||
if private.frame then
|
||||
private.frame:SetPulsingNavButton()
|
||||
end
|
||||
for _, callback in ipairs(private.updateCallbacks) do
|
||||
callback()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AuctionUI.SetOpenPage(name)
|
||||
private.frame:SetSelectedNavButton(name, true)
|
||||
end
|
||||
|
||||
function AuctionUI.IsPageOpen(name)
|
||||
if not private.frame then
|
||||
return false
|
||||
end
|
||||
return private.frame:GetSelectedNavButton() == name
|
||||
end
|
||||
|
||||
function AuctionUI.IsScanning()
|
||||
return private.scanningPage and true or false
|
||||
end
|
||||
|
||||
function AuctionUI.RegisterUpdateCallback(callback)
|
||||
tinsert(private.updateCallbacks, callback)
|
||||
end
|
||||
|
||||
function AuctionUI.IsVisible()
|
||||
return private.frame and true or false
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Main Frame
|
||||
-- ============================================================================
|
||||
|
||||
function private.AuctionFrameInit()
|
||||
local tabTemplateName = nil
|
||||
if TSM.IsWowClassic() then
|
||||
private.defaultFrame = AuctionFrame
|
||||
tabTemplateName = "AuctionTabTemplate"
|
||||
else
|
||||
private.defaultFrame = AuctionHouseFrame
|
||||
tabTemplateName = "AuctionHouseFrameTabTemplate"
|
||||
end
|
||||
if not private.hasShown then
|
||||
private.hasShown = true
|
||||
local tabId = private.defaultFrame.numTabs + 1
|
||||
local tab = CreateFrame("Button", "AuctionFrameTab"..tabId, private.defaultFrame, tabTemplateName)
|
||||
tab:Hide()
|
||||
tab:SetID(tabId)
|
||||
tab:SetText(Log.ColorUserAccentText("TSM4"))
|
||||
tab:SetNormalFontObject(GameFontHighlightSmall)
|
||||
if TSM.IsWowClassic() then
|
||||
tab:SetPoint("LEFT", _G["AuctionFrameTab"..tabId - 1], "RIGHT", -8, 0)
|
||||
else
|
||||
tab:SetPoint("LEFT", AuctionHouseFrame.Tabs[tabId - 1], "RIGHT", -15, 0)
|
||||
tinsert(AuctionHouseFrame.Tabs, tab)
|
||||
end
|
||||
tab:Show()
|
||||
PanelTemplates_SetNumTabs(private.defaultFrame, tabId)
|
||||
PanelTemplates_EnableTab(private.defaultFrame, tabId)
|
||||
ScriptWrapper.Set(tab, "OnClick", private.TSMTabOnClick)
|
||||
end
|
||||
if private.settings.showDefault then
|
||||
UIParent_OnEvent(UIParent, "AUCTION_HOUSE_SHOW")
|
||||
else
|
||||
PlaySound(SOUNDKIT.AUCTION_WINDOW_OPEN)
|
||||
private.ShowAuctionFrame()
|
||||
end
|
||||
end
|
||||
|
||||
function private.ShowAuctionFrame()
|
||||
if private.frame then
|
||||
return
|
||||
end
|
||||
private.frame = private.CreateMainFrame()
|
||||
private.frame:Show()
|
||||
private.frame:Draw()
|
||||
for _, callback in ipairs(private.updateCallbacks) do
|
||||
callback()
|
||||
end
|
||||
end
|
||||
|
||||
function private.HideAuctionFrame()
|
||||
if not private.frame then
|
||||
return
|
||||
end
|
||||
private.frame:Hide()
|
||||
assert(not private.frame)
|
||||
for _, callback in ipairs(private.updateCallbacks) do
|
||||
callback()
|
||||
end
|
||||
end
|
||||
|
||||
function private.CreateMainFrame()
|
||||
TSM.UI.AnalyticsRecordPathChange("auction")
|
||||
local frame = UIElements.New("LargeApplicationFrame", "base")
|
||||
:SetParent(UIParent)
|
||||
:SetSettingsContext(private.settings, "frame")
|
||||
:SetMinResize(MIN_FRAME_SIZE.width, MIN_FRAME_SIZE.height)
|
||||
:SetStrata("HIGH")
|
||||
:SetProtected(TSM.db.global.coreOptions.protectAuctionHouse)
|
||||
:AddPlayerGold()
|
||||
:AddAppStatusIcon()
|
||||
:AddSwitchButton(private.SwitchBtnOnClick)
|
||||
:SetScript("OnHide", private.BaseFrameOnHide)
|
||||
for _, info in ipairs(private.topLevelPages) do
|
||||
frame:AddNavButton(info.name, info.callback)
|
||||
end
|
||||
local whatsNewDialog = TSM.UI.WhatsNew.GetDialog()
|
||||
if whatsNewDialog then
|
||||
frame:ShowDialogFrame(whatsNewDialog)
|
||||
end
|
||||
return frame
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Local Script Handlers
|
||||
-- ============================================================================
|
||||
|
||||
function private.BaseFrameOnHide(frame)
|
||||
assert(frame == private.frame)
|
||||
frame:Release()
|
||||
private.frame = nil
|
||||
if not private.isSwitching then
|
||||
PlaySound(SOUNDKIT.AUCTION_WINDOW_CLOSE)
|
||||
if TSM.IsWowClassic() then
|
||||
CloseAuctionHouse()
|
||||
else
|
||||
C_AuctionHouse.CloseAuctionHouse()
|
||||
end
|
||||
end
|
||||
TSM.UI.AnalyticsRecordClose("auction")
|
||||
end
|
||||
|
||||
function private.SwitchBtnOnClick(button)
|
||||
private.isSwitching = true
|
||||
private.settings.showDefault = true
|
||||
private.HideAuctionFrame()
|
||||
UIParent_OnEvent(UIParent, "AUCTION_HOUSE_SHOW")
|
||||
private.isSwitching = false
|
||||
end
|
||||
|
||||
local function NoOp()
|
||||
-- do nothing - what did you expect?
|
||||
end
|
||||
|
||||
function private.TSMTabOnClick()
|
||||
private.settings.showDefault = false
|
||||
if TSM.IsWowClassic() then
|
||||
ClearCursor()
|
||||
ClickAuctionSellItemButton(AuctionsItemButton, "LeftButton")
|
||||
end
|
||||
ClearCursor()
|
||||
-- Replace CloseAuctionHouse() with a no-op while hiding the AH frame so we don't stop interacting with the AH NPC
|
||||
if TSM.IsWowClassic() then
|
||||
local origCloseAuctionHouse = CloseAuctionHouse
|
||||
CloseAuctionHouse = NoOp
|
||||
AuctionFrame_Hide()
|
||||
CloseAuctionHouse = origCloseAuctionHouse
|
||||
else
|
||||
local origCloseAuctionHouse = C_AuctionHouse.CloseAuctionHouse
|
||||
C_AuctionHouse.CloseAuctionHouse = NoOp
|
||||
HideUIPanel(private.defaultFrame)
|
||||
C_AuctionHouse.CloseAuctionHouse = origCloseAuctionHouse
|
||||
end
|
||||
private.ShowAuctionFrame()
|
||||
end
|
||||
|
||||
function private.ItemLinkedCallback(name, itemLink)
|
||||
if not private.frame then
|
||||
return
|
||||
end
|
||||
local path = private.frame:GetSelectedNavButton()
|
||||
for _, info in ipairs(private.topLevelPages) do
|
||||
if info.name == path then
|
||||
if info.itemLinkedHandler(name, itemLink) then
|
||||
return true
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
error("Invalid frame path")
|
||||
end
|
||||
715
Core/UI/AuctionUI/MyAuctions.lua
Normal file
715
Core/UI/AuctionUI/MyAuctions.lua
Normal file
@@ -0,0 +1,715 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster --
|
||||
-- https://tradeskillmaster.com --
|
||||
-- All Rights Reserved - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local _, TSM = ...
|
||||
local MyAuctions = TSM.UI.AuctionUI:NewPackage("MyAuctions")
|
||||
local L = TSM.Include("Locale").GetTable()
|
||||
local FSM = TSM.Include("Util.FSM")
|
||||
local Money = TSM.Include("Util.Money")
|
||||
local String = TSM.Include("Util.String")
|
||||
local Math = TSM.Include("Util.Math")
|
||||
local TempTable = TSM.Include("Util.TempTable")
|
||||
local ItemString = TSM.Include("Util.ItemString")
|
||||
local Theme = TSM.Include("Util.Theme")
|
||||
local ItemInfo = TSM.Include("Service.ItemInfo")
|
||||
local Settings = TSM.Include("Service.Settings")
|
||||
local UIElements = TSM.Include("UI.UIElements")
|
||||
local private = {
|
||||
settings = nil,
|
||||
fsm = nil,
|
||||
frame = nil,
|
||||
query = nil,
|
||||
}
|
||||
local DURATION_LIST = {
|
||||
L["None"],
|
||||
AUCTION_TIME_LEFT1_DETAIL,
|
||||
AUCTION_TIME_LEFT2_DETAIL,
|
||||
AUCTION_TIME_LEFT3_DETAIL,
|
||||
AUCTION_TIME_LEFT4_DETAIL,
|
||||
}
|
||||
local SECONDS_PER_MIN = 60
|
||||
local SECONDS_PER_HOUR = 60 * SECONDS_PER_MIN
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Module Functions
|
||||
-- ============================================================================
|
||||
|
||||
function MyAuctions.OnInitialize()
|
||||
private.settings = Settings.NewView()
|
||||
:AddKey("global", "auctionUIContext", "myAuctionsScrollingTable")
|
||||
private.FSMCreate()
|
||||
TSM.UI.AuctionUI.RegisterTopLevelPage(L["My Auctions"], private.GetMyAuctionsFrame, private.OnItemLinked)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- MyAuctions UI
|
||||
-- ============================================================================
|
||||
|
||||
function private.GetMyAuctionsFrame()
|
||||
TSM.UI.AnalyticsRecordPathChange("auction", "my_auctions")
|
||||
private.query = private.query or TSM.MyAuctions.CreateQuery()
|
||||
local frame = UIElements.New("Frame", "myAuctions")
|
||||
:SetLayout("VERTICAL")
|
||||
:SetBackgroundColor("PRIMARY_BG_ALT")
|
||||
:AddChild(UIElements.New("Frame", "header")
|
||||
:SetLayout("VERTICAL")
|
||||
:SetHeight(72)
|
||||
:SetPadding(8)
|
||||
:AddChild(UIElements.New("Frame", "filters")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(24)
|
||||
:SetMargin(0, 0, 0, 8)
|
||||
:AddChild(UIElements.New("SelectionDropdown", "duration")
|
||||
:SetWidth(232)
|
||||
:SetItems(DURATION_LIST)
|
||||
:SetHintText(L["Filter by duration"])
|
||||
:SetScript("OnSelectionChanged", private.DurationFilterChanged)
|
||||
)
|
||||
:AddChild(UIElements.New("GroupSelector", "group")
|
||||
:SetWidth(232)
|
||||
:SetMargin(8, 8, 0, 0)
|
||||
:SetHintText(L["Filter by groups"])
|
||||
:SetScript("OnSelectionChanged", private.FilterChanged)
|
||||
)
|
||||
:AddChild(UIElements.New("Input", "keyword")
|
||||
:SetIconTexture("iconPack.18x18/Search")
|
||||
:AllowItemInsert(false)
|
||||
:SetClearButtonEnabled(true)
|
||||
:SetHintText(L["Filter by keyword"])
|
||||
:SetScript("OnValueChanged", private.FilterChanged)
|
||||
)
|
||||
)
|
||||
:AddChild(UIElements.New("Frame", "buttons")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(24)
|
||||
:AddChild(UIElements.New("Checkbox", "ignoreBid")
|
||||
:SetWidth("AUTO")
|
||||
:SetCheckboxPosition("LEFT")
|
||||
:SetText(L["Hide auctions with bids"])
|
||||
:SetScript("OnValueChanged", private.ToggleFilterChanged)
|
||||
)
|
||||
:AddChild(UIElements.New("Checkbox", "onlyBid")
|
||||
:SetMargin(16, 0, 0, 0)
|
||||
:SetWidth("AUTO")
|
||||
:SetCheckboxPosition("LEFT")
|
||||
:SetText(L["Show only auctions with bids"])
|
||||
:SetScript("OnValueChanged", private.ToggleFilterChanged)
|
||||
)
|
||||
:AddChild(UIElements.New("Checkbox", "onlySold")
|
||||
:SetMargin(16, 0, 0, 0)
|
||||
:SetWidth("AUTO")
|
||||
:SetCheckboxPosition("LEFT")
|
||||
:SetText(L["Only show sold auctions"])
|
||||
:SetScript("OnValueChanged", private.ToggleFilterChanged)
|
||||
)
|
||||
:AddChild(UIElements.New("Spacer"))
|
||||
:AddChild(UIElements.New("ActionButton", "clearfilter")
|
||||
:SetSize(142, 24)
|
||||
:SetText(L["Clear Filters"])
|
||||
:SetScript("OnClick", private.ClearFilterOnClick)
|
||||
)
|
||||
)
|
||||
)
|
||||
if TSM.IsWowClassic() then
|
||||
frame:AddChild(UIElements.New("MyAuctionsScrollingTable", "auctions")
|
||||
:SetSettingsContext(private.settings, "myAuctionsScrollingTable")
|
||||
:GetScrollingTableInfo()
|
||||
:NewColumn("item")
|
||||
:SetTitle(L["Item Name"])
|
||||
:SetIconSize(12)
|
||||
:SetFont("ITEM_BODY3")
|
||||
:SetJustifyH("LEFT")
|
||||
:SetTextInfo(nil, private.AuctionsGetItemText)
|
||||
:SetIconInfo("itemString", ItemInfo.GetTexture)
|
||||
:SetTooltipInfo("itemString", private.AuctionsGetItemTooltip)
|
||||
:SetActionIconInfo(1, 12, private.AuctionsGetSoldIcon)
|
||||
:DisableHiding()
|
||||
:Commit()
|
||||
:NewColumn("stackSize")
|
||||
:SetTitle(L["Qty"])
|
||||
:SetFont("TABLE_TABLE1")
|
||||
:SetJustifyH("RIGHT")
|
||||
:SetTextInfo(nil, private.AuctionsGetStackSizeText)
|
||||
:Commit()
|
||||
:NewColumn("timeLeft")
|
||||
:SetTitleIcon("iconPack.14x14/Clock")
|
||||
:SetFont("BODY_BODY3")
|
||||
:SetJustifyH("CENTER")
|
||||
:SetTextInfo(nil, private.AuctionsGetTimeLeftText)
|
||||
:Commit()
|
||||
:NewColumn("highbidder")
|
||||
:SetTitle(L["High Bidder"])
|
||||
:SetFont("BODY_BODY3")
|
||||
:SetJustifyH("LEFT")
|
||||
:SetTextInfo(nil, private.AuctionsGetHighBidderText)
|
||||
:Commit()
|
||||
:NewColumn("group")
|
||||
:SetTitle(GROUP)
|
||||
:SetFont("BODY_BODY3")
|
||||
:SetJustifyH("LEFT")
|
||||
:SetTextInfo(nil, private.AuctionsGetGroupNameText)
|
||||
:Commit()
|
||||
:NewColumn("currentBid")
|
||||
:SetTitle(BID)
|
||||
:SetFont("TABLE_TABLE1")
|
||||
:SetJustifyH("RIGHT")
|
||||
:SetTextInfo(nil, private.AuctionsGetCurrentBidText)
|
||||
:Commit()
|
||||
:NewColumn("buyout")
|
||||
:SetTitle(BUYOUT)
|
||||
:SetFont("TABLE_TABLE1")
|
||||
:SetJustifyH("RIGHT")
|
||||
:SetTextInfo(nil, private.AuctionsGetCurrentBuyoutText)
|
||||
:Commit()
|
||||
:Commit()
|
||||
:SetQuery(private.query)
|
||||
:SetSelectionValidator(private.AuctionsValidateSelection)
|
||||
:SetScript("OnSelectionChanged", private.AuctionsOnSelectionChanged)
|
||||
:SetScript("OnDataUpdated", private.AuctionsOnDataUpdated)
|
||||
)
|
||||
else
|
||||
frame:AddChild(UIElements.New("MyAuctionsScrollingTable", "auctions")
|
||||
:SetSettingsContext(private.settings, "myAuctionsScrollingTable")
|
||||
:GetScrollingTableInfo()
|
||||
:NewColumn("item")
|
||||
:SetTitle(L["Item Name"])
|
||||
:SetIconSize(12)
|
||||
:SetFont("ITEM_BODY3")
|
||||
:SetJustifyH("LEFT")
|
||||
:SetTextInfo(nil, private.AuctionsGetItemText)
|
||||
:SetIconInfo("itemString", ItemInfo.GetTexture)
|
||||
:SetTooltipInfo("itemString", private.AuctionsGetItemTooltip)
|
||||
:SetActionIconInfo(1, 12, private.AuctionsGetSoldIcon)
|
||||
:SetSortInfo("name")
|
||||
:DisableHiding()
|
||||
:Commit()
|
||||
:NewColumn("stackSize")
|
||||
:SetTitle(L["Qty"])
|
||||
:SetFont("TABLE_TABLE1")
|
||||
:SetJustifyH("RIGHT")
|
||||
:SetTextInfo(nil, private.AuctionsGetStackSizeText)
|
||||
:SetSortInfo("stackSize")
|
||||
:Commit()
|
||||
:NewColumn("timeLeft")
|
||||
:SetTitleIcon("iconPack.14x14/Clock")
|
||||
:SetFont("BODY_BODY3")
|
||||
:SetJustifyH("CENTER")
|
||||
:SetTextInfo(nil, private.AuctionsGetTimeLeftText)
|
||||
:SetSortInfo("duration")
|
||||
:Commit()
|
||||
:NewColumn("group")
|
||||
:SetTitle(GROUP)
|
||||
:SetFont("BODY_BODY3")
|
||||
:SetJustifyH("LEFT")
|
||||
:SetTextInfo(nil, private.AuctionsGetGroupNameText)
|
||||
:SetSortInfo("group")
|
||||
:Commit()
|
||||
:NewColumn("currentBid")
|
||||
:SetTitle(BID)
|
||||
:SetFont("TABLE_TABLE1")
|
||||
:SetJustifyH("RIGHT")
|
||||
:SetTextInfo(nil, private.AuctionsGetCurrentBidText)
|
||||
:SetSortInfo("currentBid")
|
||||
:Commit()
|
||||
:NewColumn("buyout")
|
||||
:SetTitle(BUYOUT)
|
||||
:SetFont("TABLE_TABLE1")
|
||||
:SetJustifyH("RIGHT")
|
||||
:SetTextInfo(nil, private.AuctionsGetCurrentBuyoutText)
|
||||
:SetSortInfo("buyout")
|
||||
:Commit()
|
||||
:Commit()
|
||||
:SetQuery(private.query)
|
||||
:SetSelectionValidator(private.AuctionsValidateSelection)
|
||||
:SetScript("OnSelectionChanged", private.AuctionsOnSelectionChanged)
|
||||
:SetScript("OnDataUpdated", private.AuctionsOnDataUpdated)
|
||||
)
|
||||
end
|
||||
frame:AddChild(UIElements.New("Texture", "line")
|
||||
:SetHeight(2)
|
||||
:SetTexture("ACTIVE_BG")
|
||||
)
|
||||
:AddChild(UIElements.New("Frame", "bottom")
|
||||
:SetLayout("VERTICAL")
|
||||
:SetHeight(68)
|
||||
:SetPadding(8)
|
||||
:SetBackgroundColor("PRIMARY_BG_ALT")
|
||||
:AddChild(UIElements.New("Frame", "row1")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(20)
|
||||
:SetMargin(0, 0, 0, 8)
|
||||
:AddChild(UIElements.New("Text", "sold")
|
||||
:SetWidth("AUTO")
|
||||
:SetFont("BODY_BODY3_MEDIUM")
|
||||
)
|
||||
:AddChild(UIElements.New("Text", "soldValue")
|
||||
:SetWidth("AUTO")
|
||||
:SetFont("TABLE_TABLE1")
|
||||
)
|
||||
:AddChild(UIElements.New("Texture", "vline")
|
||||
:SetWidth(1)
|
||||
:SetMargin(8, 8, 0, 0)
|
||||
:SetTexture("ACTIVE_BG_ALT")
|
||||
)
|
||||
:AddChild(UIElements.New("Text", "posted")
|
||||
:SetWidth("AUTO")
|
||||
:SetFont("BODY_BODY3_MEDIUM")
|
||||
)
|
||||
:AddChild(UIElements.New("Text", "postedValue")
|
||||
:SetWidth("AUTO")
|
||||
:SetFont("TABLE_TABLE1")
|
||||
)
|
||||
:AddChild(UIElements.New("Spacer", "spacer"))
|
||||
)
|
||||
:AddChild(UIElements.New("Frame", "row2")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(24)
|
||||
:AddChild(UIElements.New("ProgressBar", "progressBar")
|
||||
:SetMargin(0, 8, 0, 0)
|
||||
:SetProgress(0)
|
||||
)
|
||||
:AddChild(UIElements.NewNamed("ActionButton", "cancelBtn", "TSMCancelAuctionBtn")
|
||||
:SetSize(110, 24)
|
||||
:SetMargin(0, 8, 0, 0)
|
||||
:SetText(CANCEL)
|
||||
:SetDisabled(true)
|
||||
:DisableClickCooldown(true)
|
||||
:SetScript("OnClick", private.CancelButtonOnClick)
|
||||
)
|
||||
:AddChild(UIElements.New("ActionButton", "skipBtn")
|
||||
:SetSize(110, 24)
|
||||
:SetText(L["Skip"])
|
||||
:SetDisabled(true)
|
||||
:DisableClickCooldown(true)
|
||||
:SetScript("OnClick", private.SkipButtonOnClick)
|
||||
)
|
||||
)
|
||||
)
|
||||
:SetScript("OnUpdate", private.FrameOnUpdate)
|
||||
:SetScript("OnHide", private.FrameOnHide)
|
||||
private.frame = frame
|
||||
return frame
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Local Script Handlers
|
||||
-- ============================================================================
|
||||
|
||||
function private.OnItemLinked(name)
|
||||
private.frame:GetElement("header.filters.keyword")
|
||||
:SetValue(name)
|
||||
:Draw()
|
||||
private.FilterChanged()
|
||||
return true
|
||||
end
|
||||
|
||||
function private.FrameOnUpdate(frame)
|
||||
frame:SetScript("OnUpdate", nil)
|
||||
private.fsm:ProcessEvent("EV_FRAME_SHOWN", frame)
|
||||
end
|
||||
|
||||
function private.FrameOnHide(frame)
|
||||
assert(frame == private.frame)
|
||||
private.frame = nil
|
||||
private.fsm:ProcessEvent("EV_FRAME_HIDDEN")
|
||||
end
|
||||
|
||||
function private.ToggleFilterChanged(toggle)
|
||||
local ignoreBidToggle = toggle:GetElement("__parent.ignoreBid")
|
||||
local onlyBidToggle = toggle:GetElement("__parent.onlyBid")
|
||||
local onlySoldToggle = toggle:GetElement("__parent.onlySold")
|
||||
if ignoreBidToggle:IsChecked() and onlyBidToggle:IsChecked() then
|
||||
-- uncheck the other toggle in the pair of "bid" toggles
|
||||
if toggle == ignoreBidToggle then
|
||||
onlyBidToggle:SetChecked(false, true)
|
||||
:Draw()
|
||||
else
|
||||
ignoreBidToggle:SetChecked(false, true)
|
||||
:Draw()
|
||||
end
|
||||
end
|
||||
if onlyBidToggle:IsChecked() and onlySoldToggle:IsChecked() then
|
||||
-- uncheck the other toggle in the pair of "only" toggles
|
||||
if toggle == onlyBidToggle then
|
||||
onlySoldToggle:SetChecked(false, true)
|
||||
:Draw()
|
||||
else
|
||||
onlyBidToggle:SetChecked(false, true)
|
||||
:Draw()
|
||||
end
|
||||
end
|
||||
private.FilterChanged()
|
||||
end
|
||||
|
||||
function private.DurationFilterChanged(dropdown)
|
||||
if dropdown:GetSelectedItemKey() == 1 then
|
||||
-- none
|
||||
dropdown:SetSelectedItem(nil, true)
|
||||
end
|
||||
private.FilterChanged()
|
||||
end
|
||||
|
||||
function private.FilterChanged()
|
||||
private.fsm:ProcessEvent("EV_FILTER_UPDATED")
|
||||
end
|
||||
|
||||
function private.ClearFilterOnClick(button)
|
||||
button:GetElement("__parent.__parent.filters.duration")
|
||||
:SetOpen(false)
|
||||
:SetSelectedItem()
|
||||
button:GetElement("__parent.__parent.filters.group")
|
||||
:ClearSelectedGroups()
|
||||
button:GetElement("__parent.__parent.filters.keyword")
|
||||
:SetValue("")
|
||||
:SetFocused(false)
|
||||
button:GetElement("__parent.ignoreBid")
|
||||
:SetChecked(false, true)
|
||||
button:GetElement("__parent.onlyBid")
|
||||
:SetChecked(false, true)
|
||||
button:GetElement("__parent.onlySold")
|
||||
:SetChecked(false, true)
|
||||
button:GetParentElement():GetParentElement():Draw()
|
||||
private.fsm:ProcessEvent("EV_FILTER_UPDATED")
|
||||
end
|
||||
|
||||
function private.AuctionsValidateSelection(_, row)
|
||||
return row:GetField("saleStatus") == 0
|
||||
end
|
||||
|
||||
function private.AuctionsOnSelectionChanged()
|
||||
private.fsm:ProcessEvent("EV_SELECTION_CHANGED")
|
||||
end
|
||||
|
||||
function private.AuctionsOnDataUpdated()
|
||||
if not private.frame then
|
||||
return
|
||||
end
|
||||
|
||||
private.fsm:SetLoggingEnabled(false)
|
||||
private.fsm:ProcessEvent("EV_DATA_UPDATED")
|
||||
private.fsm:SetLoggingEnabled(true)
|
||||
end
|
||||
|
||||
function private.CancelButtonOnClick(button)
|
||||
private.fsm:ProcessEvent("EV_CANCEL_CLICKED")
|
||||
end
|
||||
|
||||
function private.SkipButtonOnClick(button)
|
||||
private.fsm:ProcessEvent("EV_SKIP_CLICKED")
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- FSM
|
||||
-- ============================================================================
|
||||
|
||||
function private.FSMCreate()
|
||||
local fsmContext = {
|
||||
frame = nil,
|
||||
durationFilter = nil,
|
||||
keywordFilter = nil,
|
||||
groupFilter = {},
|
||||
bidFilter = nil,
|
||||
soldFilter = false,
|
||||
filterChanged = false,
|
||||
}
|
||||
local function UpdateFrame(context)
|
||||
if not context.frame then
|
||||
return
|
||||
end
|
||||
|
||||
local auctions = context.frame:GetElement("auctions")
|
||||
if context.filterChanged then
|
||||
context.filterChanged = false
|
||||
private.query:ResetFilters()
|
||||
if context.durationFilter then
|
||||
if TSM.IsWowClassic() then
|
||||
private.query:Equal("duration", context.durationFilter)
|
||||
else
|
||||
if context.durationFilter == 1 then
|
||||
private.query:LessThan("duration", time() + (30 * SECONDS_PER_MIN))
|
||||
elseif context.durationFilter == 2 then
|
||||
private.query:LessThan("duration", time() + (2 * SECONDS_PER_HOUR))
|
||||
elseif context.durationFilter == 3 then
|
||||
private.query:LessThanOrEqual("duration", time() + (12 * SECONDS_PER_HOUR))
|
||||
else
|
||||
private.query:GreaterThan("duration", time() + (12 * SECONDS_PER_HOUR))
|
||||
end
|
||||
end
|
||||
end
|
||||
if context.keywordFilter then
|
||||
private.query:Matches("itemName", context.keywordFilter)
|
||||
end
|
||||
if next(context.groupFilter) then
|
||||
private.query:InTable("group", context.groupFilter)
|
||||
end
|
||||
if context.bidFilter ~= nil then
|
||||
if context.bidFilter then
|
||||
private.query:NotEqual("highBidder", "")
|
||||
else
|
||||
private.query:Equal("highBidder", "")
|
||||
end
|
||||
end
|
||||
if context.soldFilter then
|
||||
private.query:Equal("saleStatus", 1)
|
||||
end
|
||||
auctions:SetQuery(private.query, true)
|
||||
end
|
||||
local selectedRow = auctions:GetSelection()
|
||||
local hasFilter = context.durationFilter or context.keywordFilter or next(context.groupFilter) or context.bidFilter ~= nil or context.soldFilter
|
||||
context.frame:GetElement("header.buttons.clearfilter")
|
||||
:SetDisabled(not hasFilter)
|
||||
:Draw()
|
||||
|
||||
local numPending = TSM.MyAuctions.GetNumPending()
|
||||
local progressText = nil
|
||||
if numPending > 0 then
|
||||
progressText = format(L["Canceling %d Auctions..."], numPending)
|
||||
elseif selectedRow then
|
||||
progressText = L["Ready to Cancel"]
|
||||
else
|
||||
progressText = L["Select Auction to Cancel"]
|
||||
end
|
||||
local row2 = context.frame:GetElement("bottom.row2")
|
||||
row2:GetElement("cancelBtn")
|
||||
:SetDisabled(not selectedRow or (not TSM.IsWowClassic() and numPending > 0) or (not TSM.IsWowClassic() and C_AuctionHouse.GetCancelCost(selectedRow:GetField("auctionId")) > GetMoney()))
|
||||
row2:GetElement("skipBtn")
|
||||
:SetDisabled(not selectedRow)
|
||||
row2:GetElement("progressBar")
|
||||
:SetProgressIconHidden(numPending == 0)
|
||||
:SetText(progressText)
|
||||
row2:Draw()
|
||||
local numPosted, numSold, postedGold, soldGold = 0, 0, 0, 0
|
||||
for _, row in private.query:Iterator() do
|
||||
local itemString, saleStatus, buyout, currentBid, stackSize = row:GetFields("itemString", "saleStatus", "buyout", "currentBid", "stackSize")
|
||||
if saleStatus == 1 then
|
||||
numSold = numSold + 1
|
||||
-- if somebody did a buyout, then bid will be equal to buyout, otherwise it'll be the winning bid
|
||||
soldGold = soldGold + currentBid
|
||||
else
|
||||
numPosted = numPosted + 1
|
||||
if ItemInfo.IsCommodity(itemString) then
|
||||
postedGold = postedGold + (buyout * stackSize)
|
||||
else
|
||||
postedGold = postedGold + buyout
|
||||
end
|
||||
end
|
||||
end
|
||||
local row1 = context.frame:GetElement("bottom.row1")
|
||||
row1:GetElement("sold")
|
||||
:SetFormattedText((hasFilter and L["%s Sold Auctions (Filtered)"] or L["%s Sold Auctions"])..":", Theme.GetColor("INDICATOR"):ColorText(numSold))
|
||||
row1:GetElement("soldValue")
|
||||
:SetText(Money.ToString(soldGold))
|
||||
row1:GetElement("posted")
|
||||
:SetFormattedText((hasFilter and L["%s Posted Auctions (Filtered)"] or L["%s Posted Auctions"])..":", Theme.GetColor("INDICATOR_ALT"):ColorText(numPosted))
|
||||
row1:GetElement("postedValue")
|
||||
:SetText(Money.ToString(postedGold))
|
||||
row1:Draw()
|
||||
end
|
||||
private.fsm = FSM.New("MY_AUCTIONS")
|
||||
:AddState(FSM.NewState("ST_HIDDEN")
|
||||
:SetOnEnter(function(context)
|
||||
context.frame = nil
|
||||
context.durationFilter = nil
|
||||
context.keywordFilter = nil
|
||||
wipe(context.groupFilter)
|
||||
context.bidFilter = nil
|
||||
context.soldFilter = false
|
||||
end)
|
||||
:AddTransition("ST_HIDDEN")
|
||||
:AddTransition("ST_SHOWNING")
|
||||
:AddEventTransition("EV_FRAME_SHOWN", "ST_SHOWNING")
|
||||
)
|
||||
:AddState(FSM.NewState("ST_SHOWNING")
|
||||
:SetOnEnter(function(context, frame)
|
||||
context.frame = frame
|
||||
context.filterChanged = true
|
||||
return "ST_SHOWN"
|
||||
end)
|
||||
:AddTransition("ST_SHOWN")
|
||||
)
|
||||
:AddState(FSM.NewState("ST_SHOWN")
|
||||
:SetOnEnter(function(context)
|
||||
UpdateFrame(context)
|
||||
end)
|
||||
:AddTransition("ST_HIDDEN")
|
||||
:AddTransition("ST_SHOWN")
|
||||
:AddTransition("ST_CANCELING")
|
||||
:AddEventTransition("EV_CANCEL_CLICKED", "ST_CANCELING")
|
||||
:AddEventTransition("EV_SELECTION_CHANGED", "ST_SHOWN")
|
||||
:AddEventTransition("EV_DATA_UPDATED", "ST_SHOWN")
|
||||
:AddEvent("EV_SKIP_CLICKED", function(context)
|
||||
context.frame:GetElement("auctions"):SelectNextRow()
|
||||
return "ST_SHOWN"
|
||||
end)
|
||||
:AddEvent("EV_FILTER_UPDATED", function(context)
|
||||
local didChange = false
|
||||
local durationFilter = context.frame:GetElement("header.filters.duration"):GetSelectedItemKey()
|
||||
durationFilter = durationFilter and (durationFilter - 1) or nil
|
||||
if durationFilter ~= context.durationFilter then
|
||||
context.durationFilter = durationFilter
|
||||
didChange = true
|
||||
end
|
||||
local keywordFilter = context.frame:GetElement("header.filters.keyword"):GetValue()
|
||||
keywordFilter = keywordFilter ~= "" and String.Escape(keywordFilter) or nil
|
||||
if keywordFilter ~= context.keywordFilter then
|
||||
context.keywordFilter = keywordFilter
|
||||
didChange = true
|
||||
end
|
||||
local newGroupFilter = TempTable.Acquire()
|
||||
for groupPath in context.frame:GetElement("header.filters.group"):SelectedGroupIterator() do
|
||||
newGroupFilter[groupPath] = true
|
||||
end
|
||||
if Math.CalculateHash(newGroupFilter) ~= Math.CalculateHash(context.groupFilter) then
|
||||
didChange = true
|
||||
wipe(context.groupFilter)
|
||||
for groupPath in pairs(newGroupFilter) do
|
||||
context.groupFilter[groupPath] = true
|
||||
end
|
||||
end
|
||||
TempTable.Release(newGroupFilter)
|
||||
local bidFilter = nil
|
||||
if context.frame:GetElement("header.buttons.ignoreBid"):IsChecked() then
|
||||
bidFilter = false
|
||||
elseif context.frame:GetElement("header.buttons.onlyBid"):IsChecked() then
|
||||
bidFilter = true
|
||||
end
|
||||
if bidFilter ~= context.bidFilter then
|
||||
context.bidFilter = bidFilter
|
||||
didChange = true
|
||||
end
|
||||
local soldFilter = context.frame:GetElement("header.buttons.onlySold"):IsChecked()
|
||||
if soldFilter ~= context.soldFilter then
|
||||
context.soldFilter = soldFilter
|
||||
didChange = true
|
||||
end
|
||||
if didChange then
|
||||
context.filterChanged = true
|
||||
return "ST_SHOWN"
|
||||
end
|
||||
end)
|
||||
)
|
||||
:AddState(FSM.NewState("ST_CANCELING")
|
||||
:SetOnEnter(function(context)
|
||||
local buttonsFrame = context.frame:GetElement("bottom")
|
||||
buttonsFrame:GetElement("row2.cancelBtn"):SetDisabled(true)
|
||||
buttonsFrame:GetElement("row2.skipBtn"):SetDisabled(true)
|
||||
buttonsFrame:Draw()
|
||||
local auctionId = context.frame:GetElement("auctions"):GetSelection():GetField("auctionId")
|
||||
if TSM.MyAuctions.CanCancel(auctionId) then
|
||||
TSM.MyAuctions.CancelAuction(auctionId)
|
||||
end
|
||||
return "ST_SHOWN"
|
||||
end)
|
||||
:AddTransition("ST_HIDDEN")
|
||||
:AddTransition("ST_SHOWN")
|
||||
)
|
||||
:AddDefaultEventTransition("EV_FRAME_HIDDEN", "ST_HIDDEN")
|
||||
:Init("ST_HIDDEN", fsmContext)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Private Helper Functions
|
||||
-- ============================================================================
|
||||
|
||||
function private.AuctionsGetItemText(row)
|
||||
if row:GetField("saleStatus") == 1 then
|
||||
return Theme.GetColor("INDICATOR"):ColorText(row:GetField("itemName"))
|
||||
else
|
||||
return TSM.UI.GetQualityColoredText(row:GetField("itemName"), row:GetField("itemQuality"))
|
||||
end
|
||||
end
|
||||
|
||||
function private.AuctionsGetItemTooltip(itemString)
|
||||
return itemString ~= ItemString.GetPetCage() and itemString or nil
|
||||
end
|
||||
|
||||
function private.AuctionsGetSoldIcon(self, data, iconIndex)
|
||||
assert(iconIndex == 1)
|
||||
local row = private.query:GetResultRowByUUID(data)
|
||||
if row:GetField("saleStatus") ~= 1 then
|
||||
return
|
||||
end
|
||||
return true, "iconPack.12x12/Bid", true
|
||||
end
|
||||
|
||||
function private.AuctionsGetStackSizeText(row)
|
||||
if row:GetField("saleStatus") == 1 then
|
||||
return Theme.GetColor("INDICATOR"):ColorText(row:GetField("stackSize"))
|
||||
else
|
||||
return row:GetField("stackSize")
|
||||
end
|
||||
end
|
||||
|
||||
function private.AuctionsGetTimeLeftText(row)
|
||||
local saleStatus, duration, isPending = row:GetFields("saleStatus", "duration", "isPending")
|
||||
if saleStatus == 0 and isPending then
|
||||
return "..."
|
||||
elseif saleStatus == 1 or not TSM.IsWowClassic() then
|
||||
local timeLeft = duration - time()
|
||||
local color = nil
|
||||
if saleStatus == 0 then
|
||||
if timeLeft <= 2 * SECONDS_PER_HOUR then
|
||||
color = Theme.GetFeedbackColor("RED")
|
||||
elseif timeLeft <= (TSM.IsWowClassic() and 8 or 24) * SECONDS_PER_HOUR then
|
||||
color = Theme.GetFeedbackColor("YELLOW")
|
||||
else
|
||||
color = Theme.GetFeedbackColor("GREEN")
|
||||
end
|
||||
else
|
||||
color = Theme.GetColor("INDICATOR")
|
||||
end
|
||||
local str = nil
|
||||
if timeLeft < SECONDS_PER_MIN then
|
||||
str = timeLeft.."s"
|
||||
elseif timeLeft < SECONDS_PER_HOUR then
|
||||
str = floor(timeLeft / SECONDS_PER_MIN).."m"
|
||||
else
|
||||
str = floor(timeLeft / SECONDS_PER_HOUR).."h"
|
||||
end
|
||||
return color and color:ColorText(str) or str
|
||||
else
|
||||
return TSM.UI.GetTimeLeftString(duration)
|
||||
end
|
||||
end
|
||||
|
||||
function private.AuctionsGetHighBidderText(row)
|
||||
if row:GetField("saleStatus") == 1 then
|
||||
return Theme.GetColor("INDICATOR"):ColorText(row:GetField("highBidder"))
|
||||
else
|
||||
return row:GetField("highBidder")
|
||||
end
|
||||
end
|
||||
|
||||
function private.AuctionsGetGroupNameText(row)
|
||||
local groupPath = row:GetField("group")
|
||||
local groupName = TSM.Groups.Path.GetName(groupPath)
|
||||
local level = select('#', strsplit(TSM.CONST.GROUP_SEP, groupPath))
|
||||
return Theme.GetGroupColor(level):ColorText(groupName)
|
||||
end
|
||||
|
||||
function private.AuctionsGetCurrentBidText(row)
|
||||
if row:GetField("saleStatus") == 1 then
|
||||
return Theme.GetColor("INDICATOR"):ColorText(L["Sold for:"])
|
||||
elseif not TSM.IsWowClassic() and row:GetField("highBidder") ~= "" then
|
||||
return Money.ToString(row:GetField("currentBid"), Theme.GetColor("INDICATOR"):GetTextColorPrefix())
|
||||
else
|
||||
return Money.ToString(row:GetField("currentBid"))
|
||||
end
|
||||
end
|
||||
|
||||
function private.AuctionsGetCurrentBuyoutText(row)
|
||||
return Money.ToString(row:GetField(row:GetField("saleStatus") == 1 and "currentBid" or "buyout"))
|
||||
end
|
||||
2658
Core/UI/AuctionUI/Shopping.lua
Normal file
2658
Core/UI/AuctionUI/Shopping.lua
Normal file
File diff suppressed because it is too large
Load Diff
818
Core/UI/AuctionUI/Sniper.lua
Normal file
818
Core/UI/AuctionUI/Sniper.lua
Normal file
@@ -0,0 +1,818 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster --
|
||||
-- https://tradeskillmaster.com --
|
||||
-- All Rights Reserved - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local _, TSM = ...
|
||||
local Sniper = TSM.UI.AuctionUI:NewPackage("Sniper")
|
||||
local L = TSM.Include("Locale").GetTable()
|
||||
local Delay = TSM.Include("Util.Delay")
|
||||
local Event = TSM.Include("Util.Event")
|
||||
local FSM = TSM.Include("Util.FSM")
|
||||
local Sound = TSM.Include("Util.Sound")
|
||||
local Money = TSM.Include("Util.Money")
|
||||
local Log = TSM.Include("Util.Log")
|
||||
local ItemString = TSM.Include("Util.ItemString")
|
||||
local ItemInfo = TSM.Include("Service.ItemInfo")
|
||||
local AuctionScan = TSM.Include("Service.AuctionScan")
|
||||
local MailTracking = TSM.Include("Service.MailTracking")
|
||||
local Settings = TSM.Include("Service.Settings")
|
||||
local AuctionHouseWrapper = TSM.Include("Service.AuctionHouseWrapper")
|
||||
local PlayerInfo = TSM.Include("Service.PlayerInfo")
|
||||
local UIElements = TSM.Include("UI.UIElements")
|
||||
local private = {
|
||||
settings = nil,
|
||||
fsm = nil,
|
||||
selectionFrame = nil,
|
||||
hasLastScan = nil,
|
||||
contentPath = "selection",
|
||||
}
|
||||
local PHASED_TIME = 60
|
||||
local RETAIL_RESCAN_DELAY = 30
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Module Functions
|
||||
-- ============================================================================
|
||||
|
||||
function Sniper.OnInitialize()
|
||||
private.settings = Settings.NewView()
|
||||
:AddKey("global", "auctionUIContext", "sniperScrollingTable")
|
||||
:AddKey("global", "sniperOptions", "sniperSound")
|
||||
TSM.UI.AuctionUI.RegisterTopLevelPage(L["Sniper"], private.GetSniperFrame, private.OnItemLinked)
|
||||
private.FSMCreate()
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Sniper UI
|
||||
-- ============================================================================
|
||||
|
||||
function private.GetSniperFrame()
|
||||
TSM.UI.AnalyticsRecordPathChange("auction", "sniper")
|
||||
if not private.hasLastScan then
|
||||
private.contentPath = "selection"
|
||||
end
|
||||
return UIElements.New("ViewContainer", "sniper")
|
||||
:SetNavCallback(private.GetSniperContentFrame)
|
||||
:AddPath("selection")
|
||||
:AddPath("scan")
|
||||
:SetPath(private.contentPath)
|
||||
end
|
||||
|
||||
function private.GetSniperContentFrame(viewContainer, path)
|
||||
private.contentPath = path
|
||||
if path == "selection" then
|
||||
return private.GetSelectionFrame()
|
||||
elseif path == "scan" then
|
||||
return private.GetScanFrame()
|
||||
else
|
||||
error("Unexpected path: "..tostring(path))
|
||||
end
|
||||
end
|
||||
|
||||
function private.GetSelectionFrame()
|
||||
TSM.UI.AnalyticsRecordPathChange("auction", "sniper", "selection")
|
||||
local frame = UIElements.New("Frame", "selection")
|
||||
:SetLayout("VERTICAL")
|
||||
:SetBackgroundColor("PRIMARY_BG_ALT")
|
||||
:AddChildIf(TSM.IsWowClassic(), UIElements.New("Text", "text")
|
||||
:SetHeight(20)
|
||||
:SetMargin(8, 8, 12, 0)
|
||||
:SetFont("BODY_BODY2_MEDIUM")
|
||||
:SetJustifyH("CENTER")
|
||||
:SetText(L["Start either a 'Buyout' or 'Bid' sniper using the buttons above."])
|
||||
)
|
||||
:AddChild(UIElements.New("Frame", "buttons")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(24)
|
||||
:SetMargin(8, 8, 12, 12)
|
||||
:AddChild(UIElements.New("ActionButton", "buyoutScanBtn")
|
||||
:SetMargin(0, TSM.IsWowClassic() and 8 or 0, 0, 0)
|
||||
:SetText(L["Run Buyout Sniper"])
|
||||
:SetScript("OnClick", private.BuyoutScanButtonOnClick)
|
||||
)
|
||||
:AddChildIf(TSM.IsWowClassic(), UIElements.New("ActionButton", "bidScanBtn")
|
||||
:SetText(L["Run Bid Sniper"])
|
||||
:SetScript("OnClick", private.BidScanButtonOnClick)
|
||||
)
|
||||
)
|
||||
:AddChild(UIElements.New("SniperScrollingTable", "auctions")
|
||||
:SetSettingsContext(private.settings, "sniperScrollingTable")
|
||||
)
|
||||
:SetScript("OnHide", private.SelectionFrameOnHide)
|
||||
private.selectionFrame = frame
|
||||
return frame
|
||||
end
|
||||
|
||||
function private.GetScanFrame()
|
||||
TSM.UI.AnalyticsRecordPathChange("auction", "sniper", "scan")
|
||||
return UIElements.New("Frame", "scan")
|
||||
:SetLayout("VERTICAL")
|
||||
:SetBackgroundColor("PRIMARY_BG_ALT")
|
||||
:AddChild(UIElements.New("Frame", "header")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(48)
|
||||
:SetPadding(8, 8, 14, 14)
|
||||
:AddChild(UIElements.New("ActionButton", "backBtn")
|
||||
:SetSize(64, 24)
|
||||
:SetMargin(0, 16, 0, 0)
|
||||
:SetIcon("iconPack.14x14/Chevron/Right@180")
|
||||
:SetText(BACK)
|
||||
:SetScript("OnClick", private.BackButtonOnClick)
|
||||
)
|
||||
:AddChild(UIElements.New("Text", "title")
|
||||
:SetFont("BODY_BODY2_MEDIUM")
|
||||
:SetJustifyH("CENTER")
|
||||
)
|
||||
:AddChild(UIElements.New("ActionButton", "restartBtn")
|
||||
:SetSize(80, 24)
|
||||
:SetText(L["Restart"])
|
||||
:SetScript("OnClick", private.RestartButtonOnClick)
|
||||
)
|
||||
)
|
||||
:AddChild(UIElements.New("SniperScrollingTable", "auctions")
|
||||
:SetSettingsContext(private.settings, "sniperScrollingTable")
|
||||
:SetScript("OnSelectionChanged", private.AuctionsOnSelectionChanged)
|
||||
:SetScript("OnRowRemoved", private.AuctionsOnRowRemoved)
|
||||
)
|
||||
:AddChild(UIElements.New("Texture", "line")
|
||||
:SetHeight(2)
|
||||
:SetTexture("ACTIVE_BG")
|
||||
)
|
||||
:AddChild(UIElements.New("Frame", "bottom")
|
||||
:SetLayout("HORIZONTAL")
|
||||
:SetHeight(40)
|
||||
:SetPadding(8)
|
||||
:SetBackgroundColor("PRIMARY_BG_ALT")
|
||||
:AddChild(UIElements.New("ActionButton", "pauseResumeBtn")
|
||||
:SetSize(24, 24)
|
||||
:SetMargin(0, 8, 0, 0)
|
||||
:SetIcon("iconPack.18x18/PlayPause")
|
||||
:SetScript("OnClick", private.PauseResumeBtnOnClick)
|
||||
)
|
||||
:AddChild(UIElements.New("ProgressBar", "progressBar")
|
||||
:SetHeight(24)
|
||||
:SetMargin(0, 8, 0, 0)
|
||||
:SetProgress(0)
|
||||
:SetText(L["Starting Scan..."])
|
||||
)
|
||||
:AddChild(UIElements.NewNamed("ActionButton", "actionBtn", "TSMSniperBtn")
|
||||
:SetSize(165, 24)
|
||||
:SetText(BID)
|
||||
:SetDisabled(true)
|
||||
:DisableClickCooldown(true)
|
||||
:SetScript("OnClick", private.ActionButtonOnClick)
|
||||
)
|
||||
)
|
||||
:SetScript("OnUpdate", private.ScanFrameOnUpdate)
|
||||
:SetScript("OnHide", private.ScanFrameOnHide)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Local Script Handlers
|
||||
-- ============================================================================
|
||||
|
||||
function private.OnItemLinked(name, itemLink)
|
||||
if private.selectionFrame then
|
||||
return false
|
||||
end
|
||||
private.fsm:ProcessEvent("EV_STOP_CLICKED")
|
||||
TSM.UI.AuctionUI.SetOpenPage(L["Browse"])
|
||||
TSM.UI.AuctionUI.Shopping.StartItemSearch(itemLink)
|
||||
return true
|
||||
end
|
||||
|
||||
function private.SelectionFrameOnHide(frame)
|
||||
assert(frame == private.selectionFrame)
|
||||
private.selectionFrame = nil
|
||||
end
|
||||
|
||||
function private.StartScanHelper(viewContainer, searchContext)
|
||||
if not TSM.UI.AuctionUI.StartingScan(L["Sniper"]) then
|
||||
return
|
||||
end
|
||||
viewContainer:SetPath("scan", true)
|
||||
private.fsm:ProcessEvent("EV_START_SCAN", searchContext)
|
||||
end
|
||||
|
||||
function private.BuyoutScanButtonOnClick(button)
|
||||
local viewContainer = button:GetParentElement():GetParentElement():GetParentElement()
|
||||
local searchContext = TSM.Sniper.BuyoutSearch.GetSearchContext()
|
||||
private.StartScanHelper(viewContainer, searchContext)
|
||||
end
|
||||
|
||||
function private.BidScanButtonOnClick(button)
|
||||
local viewContainer = button:GetParentElement():GetParentElement():GetParentElement()
|
||||
local searchContext = TSM.Sniper.BidSearch.GetSearchContext()
|
||||
private.StartScanHelper(viewContainer, searchContext)
|
||||
end
|
||||
|
||||
function private.AuctionsOnSelectionChanged()
|
||||
private.fsm:ProcessEvent("EV_AUCTION_SELECTION_CHANGED")
|
||||
end
|
||||
|
||||
function private.AuctionsOnRowRemoved(_, row)
|
||||
private.fsm:ProcessEvent("EV_AUCTION_ROW_REMOVED", row)
|
||||
end
|
||||
|
||||
function private.BackButtonOnClick()
|
||||
private.fsm:ProcessEvent("EV_STOP_CLICKED")
|
||||
end
|
||||
|
||||
function private.PauseResumeBtnOnClick(button)
|
||||
private.fsm:ProcessEvent("EV_PAUSE_RESUME_CLICKED")
|
||||
end
|
||||
|
||||
function private.ActionButtonOnClick(button)
|
||||
private.fsm:ProcessEvent("EV_ACTION_CLICKED")
|
||||
end
|
||||
|
||||
function private.RestartButtonOnClick(button)
|
||||
if not TSM.UI.AuctionUI.StartingScan(L["Sniper"]) then
|
||||
return
|
||||
end
|
||||
local lastScanType = private.hasLastScan
|
||||
local sniperFrame = button:GetParentElement():GetParentElement():GetParentElement()
|
||||
private.fsm:ProcessEvent("EV_STOP_CLICKED")
|
||||
if lastScanType == "bid" then
|
||||
sniperFrame:GetElement("selection.buttons.bidScanBtn"):Click()
|
||||
elseif lastScanType == "buyout" then
|
||||
sniperFrame:GetElement("selection.buttons.buyoutScanBtn"):Click()
|
||||
else
|
||||
error("Invalid last scan type: "..tostring(lastScanType))
|
||||
end
|
||||
end
|
||||
|
||||
function private.ScanFrameOnUpdate(frame)
|
||||
frame:SetScript("OnUpdate", nil)
|
||||
private.fsm:ProcessEvent("EV_SCAN_FRAME_SHOWN", frame)
|
||||
end
|
||||
|
||||
function private.ScanFrameOnHide(frame)
|
||||
private.fsm:ProcessEvent("EV_SCAN_FRAME_HIDDEN")
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- FSM
|
||||
-- ============================================================================
|
||||
|
||||
function private.FSMCreate()
|
||||
local fsmContext = {
|
||||
scanFrame = nil,
|
||||
auctionScan = nil,
|
||||
query = nil,
|
||||
progress = 0,
|
||||
progressText = L["Running Sniper Scan"],
|
||||
buttonsDisabled = true,
|
||||
findHash = nil,
|
||||
findAuction = nil,
|
||||
findResult = nil,
|
||||
numFound = 0,
|
||||
maxQuantity = 0,
|
||||
numActioned = 0,
|
||||
lastBuyQuantity = 0,
|
||||
numConfirmed = 0,
|
||||
searchContext = nil,
|
||||
scanDone = false,
|
||||
}
|
||||
Event.Register("CHAT_MSG_SYSTEM", private.FSMMessageEventHandler)
|
||||
Event.Register("UI_ERROR_MESSAGE", private.FSMMessageEventHandler)
|
||||
if not TSM.IsWowClassic() then
|
||||
Event.Register("COMMODITY_PURCHASE_SUCCEEDED", private.FSMBuyoutSuccess)
|
||||
end
|
||||
Event.Register("AUCTION_HOUSE_CLOSED", function()
|
||||
private.fsm:ProcessEvent("EV_AUCTION_HOUSE_CLOSED")
|
||||
end)
|
||||
AuctionHouseWrapper.RegisterAuctionIdUpdateCallback(function(...)
|
||||
private.fsm:ProcessEvent("EV_AUCTION_ID_UPDATE", ...)
|
||||
end)
|
||||
local function UpdateScanFrame(context)
|
||||
if not context.scanFrame or not context.searchContext then
|
||||
return
|
||||
end
|
||||
local actionText = nil
|
||||
if context.searchContext:IsBuyoutScan() then
|
||||
actionText = BUYOUT
|
||||
elseif context.searchContext:IsBidScan() then
|
||||
actionText = BID
|
||||
else
|
||||
error("Invalid scan type")
|
||||
end
|
||||
local bottom = context.scanFrame:GetElement("bottom")
|
||||
bottom:GetElement("actionBtn")
|
||||
:SetText(actionText)
|
||||
:SetDisabled(context.buttonsDisabled)
|
||||
bottom:GetElement("progressBar")
|
||||
:SetProgress(context.progress)
|
||||
:SetText(context.progressText or "")
|
||||
local auctionList = context.scanFrame:GetElement("auctions")
|
||||
:SetContext(context.auctionScan)
|
||||
:SetAuctionScan(context.auctionScan)
|
||||
:SetMarketValueFunction(context.searchContext:GetMarketValueFunc())
|
||||
if context.findAuction and not auctionList:GetSelection() then
|
||||
auctionList:SetSelection(context.findAuction)
|
||||
end
|
||||
local title = context.scanFrame:GetElement("header.title")
|
||||
if context.scanPausing or auctionList:GetSelection() then
|
||||
if context.searchContext:IsBuyoutScan() then
|
||||
title:SetText(L["Buyout Sniper Paused"])
|
||||
elseif context.searchContext:IsBidScan() then
|
||||
title:SetText(L["Bid Sniper Paused"])
|
||||
else
|
||||
error("Invalid scan type")
|
||||
end
|
||||
else
|
||||
if context.searchContext:IsBuyoutScan() then
|
||||
title:SetText(L["Buyout Sniper Running"])
|
||||
elseif context.searchContext:IsBidScan() then
|
||||
title:SetText(L["Bid Sniper Running"])
|
||||
else
|
||||
error("Invalid scan type")
|
||||
end
|
||||
end
|
||||
context.scanFrame:Draw()
|
||||
end
|
||||
local function ScanOnFilterDone(self, filter, numNewResults)
|
||||
if numNewResults > 0 then
|
||||
Sound.PlaySound(private.settings.sniperSound)
|
||||
end
|
||||
end
|
||||
private.fsm = FSM.New("SNIPER")
|
||||
:AddState(FSM.NewState("ST_INIT")
|
||||
:SetOnEnter(function(context, searchContext)
|
||||
private.hasLastScan = nil
|
||||
if context.searchContext then
|
||||
context.searchContext:KillThread()
|
||||
context.searchContext = nil
|
||||
end
|
||||
context.progress = 0
|
||||
context.progressText = L["Running Sniper Scan"]
|
||||
context.buttonsDisabled = true
|
||||
context.findHash = nil
|
||||
context.findAuction = nil
|
||||
context.findResult = nil
|
||||
context.numFound = 0
|
||||
context.numActioned = 0
|
||||
context.lastBuyQuantity = 0
|
||||
context.numConfirmed = 0
|
||||
if context.auctionScan then
|
||||
context.auctionScan:Release()
|
||||
context.auctionScan = nil
|
||||
end
|
||||
if searchContext then
|
||||
context.searchContext = searchContext
|
||||
return "ST_RUNNING_SCAN"
|
||||
elseif context.scanFrame then
|
||||
context.scanFrame:GetParentElement():SetPath("selection", true)
|
||||
context.scanFrame = nil
|
||||
end
|
||||
TSM.UI.AuctionUI.EndedScan(L["Sniper"])
|
||||
end)
|
||||
:AddTransition("ST_INIT")
|
||||
:AddTransition("ST_RUNNING_SCAN")
|
||||
:AddEventTransition("EV_START_SCAN", "ST_INIT")
|
||||
)
|
||||
:AddState(FSM.NewState("ST_RUNNING_SCAN")
|
||||
:SetOnEnter(function(context)
|
||||
context.scanDone = false
|
||||
if not context.searchContext then
|
||||
private.hasLastScan = nil
|
||||
elseif context.searchContext:IsBuyoutScan() then
|
||||
private.hasLastScan = "buyout"
|
||||
elseif context.searchContext:IsBidScan() then
|
||||
private.hasLastScan = "bid"
|
||||
else
|
||||
error("Invalid scan type")
|
||||
end
|
||||
if not context.auctionScan then
|
||||
context.auctionScan = AuctionScan.GetManager()
|
||||
:SetResolveSellers(false)
|
||||
:SetScript("OnQueryDone", ScanOnFilterDone)
|
||||
end
|
||||
if context.scanFrame then
|
||||
context.scanFrame:GetElement("bottom.progressBar"):SetProgressIconHidden(false)
|
||||
end
|
||||
UpdateScanFrame(context)
|
||||
context.searchContext:StartThread(private.FSMScanCallback, context.auctionScan)
|
||||
if TSM.IsWowClassic() then
|
||||
Delay.AfterTime("sniperPhaseDetect", PHASED_TIME, private.FSMPhasedCallback)
|
||||
end
|
||||
end)
|
||||
:SetOnExit(function(context)
|
||||
Delay.Cancel("sniperPhaseDetect")
|
||||
end)
|
||||
:AddTransition("ST_RESULTS")
|
||||
:AddTransition("ST_WAITING_FOR_PAUSE")
|
||||
:AddTransition("ST_FINDING_AUCTION")
|
||||
:AddTransition("ST_INIT")
|
||||
:AddEvent("EV_PAUSE_RESUME_CLICKED", function(context)
|
||||
return "ST_WAITING_FOR_PAUSE"
|
||||
end)
|
||||
:AddEvent("EV_SCAN_COMPLETE", function(context)
|
||||
local selection = context.scanFrame and context.scanFrame:GetElement("auctions"):GetSelection()
|
||||
if selection and selection:IsSubRow() then
|
||||
return "ST_FINDING_AUCTION"
|
||||
else
|
||||
if TSM.IsWowClassic() then
|
||||
return "ST_RESULTS"
|
||||
else
|
||||
-- wait 30 seconds before rescanning to avoid spamming the server with API calls
|
||||
context.scanDone = true
|
||||
Delay.AfterTime("SNIPER_RESCAN_DELAY", RETAIL_RESCAN_DELAY, private.FSMRescanDelayed)
|
||||
end
|
||||
end
|
||||
end)
|
||||
:AddEventTransition("EV_RESCAN_DELAYED", "ST_RESULTS")
|
||||
:AddEventTransition("EV_SCAN_FAILED", "ST_INIT")
|
||||
:AddEvent("EV_PHASED", function()
|
||||
Log.PrintUser(L["You've been phased which has caused the AH to stop working due to a bug on Blizzard's end. Please close and reopen the AH and restart Sniper."])
|
||||
return "ST_INIT"
|
||||
end)
|
||||
:AddEvent("EV_AUCTION_SELECTION_CHANGED", function(context)
|
||||
assert(context.scanFrame)
|
||||
if context.scanFrame:GetElement("auctions"):GetSelection() then
|
||||
if context.scanDone then
|
||||
return "ST_RESULTS"
|
||||
else
|
||||
-- the user selected something, so cancel the current scan
|
||||
context.auctionScan:Cancel()
|
||||
end
|
||||
end
|
||||
end)
|
||||
)
|
||||
:AddState(FSM.NewState("ST_WAITING_FOR_PAUSE")
|
||||
:SetOnEnter(function(context)
|
||||
context.scanPausing = true
|
||||
context.progressText = L["Scan Paused"]
|
||||
if context.scanFrame then
|
||||
context.scanFrame:GetElement("bottom.progressBar"):SetProgressIconHidden(true)
|
||||
end
|
||||
UpdateScanFrame(context)
|
||||
end)
|
||||
:SetOnExit(function(context)
|
||||
context.scanPausing = false
|
||||
context.progressText = L["Running Sniper Scan"]
|
||||
if context.scanFrame then
|
||||
context.scanFrame:GetElement("bottom.progressBar"):SetProgressIconHidden(false)
|
||||
end
|
||||
UpdateScanFrame(context)
|
||||
end)
|
||||
:AddEvent("EV_PAUSE_RESUME_CLICKED", function(context)
|
||||
return "ST_RESULTS"
|
||||
end)
|
||||
:AddTransition("ST_RESULTS")
|
||||
:AddTransition("ST_INIT")
|
||||
)
|
||||
:AddState(FSM.NewState("ST_RESULTS")
|
||||
:SetOnEnter(function(context)
|
||||
context.searchContext:KillThread()
|
||||
context.findAuction = nil
|
||||
context.findResult = nil
|
||||
context.numFound = 0
|
||||
context.numActioned = 0
|
||||
context.lastBuyQuantity = 0
|
||||
context.numConfirmed = 0
|
||||
context.progress = 0
|
||||
context.progressText = L["Running Sniper Scan"]
|
||||
context.buttonsDisabled = true
|
||||
UpdateScanFrame(context)
|
||||
local selection = context.scanFrame and context.scanFrame:GetElement("auctions"):GetSelection()
|
||||
if selection and selection:IsSubRow() then
|
||||
return "ST_FINDING_AUCTION"
|
||||
else
|
||||
return "ST_RUNNING_SCAN"
|
||||
end
|
||||
end)
|
||||
:AddTransition("ST_RUNNING_SCAN")
|
||||
:AddTransition("ST_AUCTION_FOUND")
|
||||
:AddTransition("ST_FINDING_AUCTION")
|
||||
:AddTransition("ST_INIT")
|
||||
)
|
||||
:AddState(FSM.NewState("ST_FINDING_AUCTION")
|
||||
:SetOnEnter(function(context)
|
||||
assert(context.scanFrame)
|
||||
context.findAuction = context.scanFrame:GetElement("auctions"):GetSelection()
|
||||
assert(context.findAuction:IsSubRow())
|
||||
context.findHash = context.findAuction:GetHashes()
|
||||
context.progress = 0
|
||||
context.progressText = L["Finding Selected Auction"]
|
||||
context.buttonsDisabled = true
|
||||
if context.scanFrame then
|
||||
context.scanFrame:GetElement("bottom.progressBar"):SetProgressIconHidden(false)
|
||||
end
|
||||
UpdateScanFrame(context)
|
||||
TSM.Shopping.SearchCommon.StartFindAuction(context.auctionScan, context.findAuction, private.FSMFindAuctionCallback, true)
|
||||
end)
|
||||
:SetOnExit(function(context)
|
||||
TSM.Shopping.SearchCommon.StopFindAuction()
|
||||
end)
|
||||
:AddTransition("ST_RESULTS")
|
||||
:AddTransition("ST_FINDING_AUCTION")
|
||||
:AddTransition("ST_AUCTION_FOUND")
|
||||
:AddTransition("ST_AUCTION_NOT_FOUND")
|
||||
:AddTransition("ST_INIT")
|
||||
:AddEventTransition("EV_AUCTION_FOUND", "ST_AUCTION_FOUND")
|
||||
:AddEventTransition("EV_AUCTION_NOT_FOUND", "ST_AUCTION_NOT_FOUND")
|
||||
:AddEvent("EV_AUCTION_SELECTION_CHANGED", function(context)
|
||||
assert(context.scanFrame)
|
||||
local selection = context.scanFrame and context.scanFrame:GetElement("auctions"):GetSelection()
|
||||
if selection and selection:IsSubRow() then
|
||||
return "ST_FINDING_AUCTION"
|
||||
else
|
||||
return "ST_RESULTS"
|
||||
end
|
||||
end)
|
||||
:AddEvent("EV_AUCTION_ROW_REMOVED", function(context, row)
|
||||
if not row:IsSubRow() then
|
||||
return
|
||||
end
|
||||
local removingFindAuction = context.findAuction == row
|
||||
row:GetResultRow():RemoveSubRow(row)
|
||||
context.scanFrame:GetElement("auctions"):UpdateData(true)
|
||||
if removingFindAuction then
|
||||
return "ST_RESULTS"
|
||||
end
|
||||
end)
|
||||
:AddEvent("EV_SCAN_FRAME_HIDDEN", function(context)
|
||||
context.scanFrame = nil
|
||||
context.findAuction = nil
|
||||
return "ST_RESULTS"
|
||||
end)
|
||||
)
|
||||
:AddState(FSM.NewState("ST_AUCTION_FOUND")
|
||||
:SetOnEnter(function(context, result)
|
||||
local selection = context.scanFrame:GetElement("auctions"):GetSelection()
|
||||
-- update the selection in case the result rows changed
|
||||
if context.findHash == selection:GetHashes() then
|
||||
context.findAuction = selection
|
||||
end
|
||||
if TSM.IsWowClassic() then
|
||||
context.findResult = result
|
||||
context.numFound = #result
|
||||
else
|
||||
local maxCommodity = context.findAuction:IsCommodity() and context.findAuction:GetResultRow():GetMaxQuantities()
|
||||
local numCanBuy = maxCommodity or result
|
||||
context.findResult = numCanBuy > 0
|
||||
context.numFound = numCanBuy
|
||||
context.maxQuantity = maxCommodity or 1
|
||||
end
|
||||
assert(context.numActioned == 0 and context.numConfirmed == 0)
|
||||
return "ST_BIDDING_BUYING"
|
||||
end)
|
||||
:AddTransition("ST_BIDDING_BUYING")
|
||||
)
|
||||
:AddState(FSM.NewState("ST_AUCTION_NOT_FOUND")
|
||||
:SetOnEnter(function(context)
|
||||
local _, rawLink = context.findAuction:GetLinks()
|
||||
context.findAuction:GetResultRow():RemoveSubRow(context.findAuction)
|
||||
Log.PrintfUser(L["Failed to find auction for %s, so removing it from the results."], rawLink)
|
||||
return "ST_RESULTS"
|
||||
end)
|
||||
:AddTransition("ST_RESULTS")
|
||||
)
|
||||
:AddState(FSM.NewState("ST_BIDDING_BUYING")
|
||||
:SetOnEnter(function(context, numToRemove)
|
||||
if numToRemove then
|
||||
-- remove the one we just bought
|
||||
context.findAuction:DecrementQuantity(numToRemove)
|
||||
context.scanFrame:GetElement("auctions"):UpdateData()
|
||||
context.findAuction = context.scanFrame and context.scanFrame:GetElement("auctions"):GetSelection()
|
||||
if context.findAuction and not context.findAuction:IsSubRow() then
|
||||
context.findAuction = nil
|
||||
end
|
||||
end
|
||||
local selection = context.scanFrame and context.scanFrame:GetElement("auctions"):GetSelection()
|
||||
if selection and not selection:IsSubRow() then
|
||||
selection = nil
|
||||
end
|
||||
local isPlayer, isHighBidder = false, false
|
||||
if selection then
|
||||
assert(selection:IsSubRow())
|
||||
local ownerStr = selection and selection:GetOwnerInfo() or nil
|
||||
isPlayer = PlayerInfo.IsPlayer(ownerStr, true, true, true)
|
||||
isHighBidder = select(4, selection:GetBidInfo())
|
||||
end
|
||||
local auctionSelected = selection and context.findHash == selection:GetHashes()
|
||||
local numCanAction = not auctionSelected and 0 or (context.numFound - context.numActioned)
|
||||
local numConfirming = context.numActioned - context.numConfirmed
|
||||
local progressText = nil
|
||||
local actionFormatStr = nil
|
||||
if context.searchContext:IsBuyoutScan() then
|
||||
actionFormatStr = L["Buy %d / %d"]
|
||||
elseif context.searchContext:IsBidScan() then
|
||||
actionFormatStr = L["Bid %d / %d"]
|
||||
else
|
||||
error("Invalid scan type")
|
||||
end
|
||||
if numConfirming == 0 and numCanAction == 0 then
|
||||
-- we're done bidding/buying and confirming this batch
|
||||
return "ST_RESULTS"
|
||||
elseif numConfirming == 0 then
|
||||
-- we can still bid/buy more
|
||||
progressText = format(actionFormatStr, context.numActioned + 1, context.numFound)
|
||||
elseif numCanAction == 0 then
|
||||
-- we're just confirming
|
||||
progressText = format(L["Confirming %d / %d"], context.numConfirmed + 1, context.numFound)
|
||||
else
|
||||
-- we can bid/buy more while confirming
|
||||
progressText = format(actionFormatStr.." ("..L["Confirming %d / %d"]..")", context.numActioned + 1, context.numFound, context.numConfirmed + 1, context.numFound)
|
||||
end
|
||||
context.progress = context.numConfirmed / context.numFound
|
||||
context.progressText = L["Scan Paused"].." - "..progressText
|
||||
if numCanAction == 0 or isPlayer or (not TSM.IsWowClassic() and numConfirming > 0) then
|
||||
context.buttonsDisabled = true
|
||||
else
|
||||
if context.searchContext:IsBuyoutScan() then
|
||||
context.buttonsDisabled = not AuctionScan.CanBuyout(selection, context.auctionScan)
|
||||
elseif context.searchContext:IsBidScan() then
|
||||
context.buttonsDisabled = not AuctionScan.CanBid(selection)
|
||||
else
|
||||
error("Invalid scan type")
|
||||
end
|
||||
end
|
||||
if context.scanFrame then
|
||||
context.scanFrame:GetElement("bottom.progressBar")
|
||||
:SetProgressIconHidden(context.numConfirmed == context.numActioned)
|
||||
context.scanFrame:GetElement("bottom.actionBtn")
|
||||
:SetDisabled(isPlayer or (isHighBidder and context.searchContext:IsBidScan()))
|
||||
:Draw()
|
||||
end
|
||||
UpdateScanFrame(context)
|
||||
end)
|
||||
:AddTransition("ST_BID_BUY_CONFIRMATION")
|
||||
:AddTransition("ST_BIDDING_BUYING")
|
||||
:AddTransition("ST_PLACING_BID_BUY")
|
||||
:AddTransition("ST_CONFIRMING_BID_BUY")
|
||||
:AddTransition("ST_RESULTS")
|
||||
:AddTransition("ST_INIT")
|
||||
:AddEvent("EV_PAUSE_RESUME_CLICKED", function(context)
|
||||
context.scanFrame:GetElement("auctions"):SetSelection(nil)
|
||||
return "ST_RESULTS"
|
||||
end)
|
||||
:AddEventTransition("EV_AUCTION_SELECTION_CHANGED", "ST_RESULTS")
|
||||
:AddEventTransition("EV_ACTION_CLICKED", "ST_BID_BUY_CONFIRMATION")
|
||||
:AddEvent("EV_CONFIRMED", function(context, isBuy, quantity)
|
||||
assert(isBuy == context.searchContext:IsBuyoutScan())
|
||||
return "ST_PLACING_BID_BUY", quantity
|
||||
end)
|
||||
:AddEvent("EV_MSG", function(context, msg)
|
||||
local _, rawLink = context.findAuction:GetLinks()
|
||||
if msg == LE_GAME_ERR_AUCTION_HIGHER_BID or msg == LE_GAME_ERR_ITEM_NOT_FOUND or msg == LE_GAME_ERR_AUCTION_BID_OWN or msg == LE_GAME_ERR_NOT_ENOUGH_MONEY or msg == LE_GAME_ERR_ITEM_MAX_COUNT then
|
||||
-- failed to bid/buy an auction
|
||||
return "ST_CONFIRMING_BID_BUY", false
|
||||
elseif context.searchContext:IsBidScan() and msg == ERR_AUCTION_BID_PLACED then
|
||||
-- bid on an auction
|
||||
return "ST_CONFIRMING_BID_BUY", true
|
||||
elseif context.searchContext:IsBuyoutScan() and msg == format(ERR_AUCTION_WON_S, ItemInfo.GetName(rawLink)) then
|
||||
-- bought an auction
|
||||
return "ST_CONFIRMING_BID_BUY", true
|
||||
end
|
||||
end)
|
||||
:AddEvent("EV_BUYOUT_SUCCESS", function(context)
|
||||
return "ST_CONFIRMING_BID_BUY", true
|
||||
end)
|
||||
:AddEvent("EV_AUCTION_ID_UPDATE", function(context, oldAuctionId, newAuctionId, newResultInfo)
|
||||
if not context.findAuction or select(2, context.findAuction:GetListingInfo()) ~= oldAuctionId then
|
||||
return
|
||||
end
|
||||
context.findAuction:UpdateResultInfo(newAuctionId, newResultInfo)
|
||||
context.findHash = context.findAuction:GetHashes()
|
||||
end)
|
||||
)
|
||||
:AddState(FSM.NewState("ST_BID_BUY_CONFIRMATION")
|
||||
:SetOnEnter(function(context)
|
||||
local selection = context.scanFrame:GetElement("auctions"):GetSelection()
|
||||
local index = TSM.IsWowClassic() and context.findResult[#context.findResult] or nil
|
||||
if TSM.UI.AuctionUI.BuyUtil.ShowConfirmation(context.scanFrame, selection, context.searchContext:IsBuyoutScan(), context.numConfirmed + 1, context.numFound, context.maxQuantity, private.FSMConfirmationCallback, context.auctionScan, index, true, context.searchContext:GetMarketValueFunc()) then
|
||||
return "ST_BIDDING_BUYING"
|
||||
else
|
||||
local quantity = selection:GetQuantities()
|
||||
return "ST_PLACING_BID_BUY", quantity
|
||||
end
|
||||
end)
|
||||
:AddTransition("ST_PLACING_BID_BUY")
|
||||
:AddTransition("ST_BIDDING_BUYING")
|
||||
)
|
||||
:AddState(FSM.NewState("ST_PLACING_BID_BUY")
|
||||
:SetOnEnter(function(context, quantity)
|
||||
local index = TSM.IsWowClassic() and tremove(context.findResult, #context.findResult) or nil
|
||||
assert(not TSM.IsWowClassic() or index)
|
||||
local bidBuyout = nil
|
||||
if context.searchContext:IsBuyoutScan() then
|
||||
bidBuyout = context.findAuction:GetBuyouts()
|
||||
elseif context.searchContext:IsBidScan() then
|
||||
bidBuyout = context.findAuction:GetRequiredBid()
|
||||
else
|
||||
error("Invalid scan type")
|
||||
end
|
||||
local result = context.auctionScan:PlaceBidOrBuyout(index, bidBuyout, context.findAuction, quantity)
|
||||
if result then
|
||||
MailTracking.RecordAuctionBuyout(ItemString.GetBaseFast(context.findAuction:GetItemString()), quantity)
|
||||
context.numActioned = context.numActioned + (TSM.IsWowClassic() and 1 or quantity)
|
||||
context.lastBuyQuantity = quantity
|
||||
else
|
||||
local _, rawLink = context.findAuction:GetLinks()
|
||||
if context.searchContext:IsBuyoutScan() then
|
||||
Log.PrintfUser(L["Failed to buy auction of %s (x%s) for %s."], rawLink, quantity, Money.ToString(bidBuyout, nil, "OPT_83_NO_COPPER"))
|
||||
elseif context.searchContext:IsBidScan() then
|
||||
Log.PrintfUser(L["Failed to bid on auction of %s (x%s) for %s."], rawLink, quantity, Money.ToString(bidBuyout, nil, "OPT_83_NO_COPPER"))
|
||||
else
|
||||
error("Invalid scan type")
|
||||
end
|
||||
end
|
||||
return "ST_BIDDING_BUYING"
|
||||
end)
|
||||
:AddTransition("ST_BIDDING_BUYING")
|
||||
)
|
||||
:AddState(FSM.NewState("ST_CONFIRMING_BID_BUY")
|
||||
:SetOnEnter(function(context, success)
|
||||
if not success then
|
||||
local _, rawLink = context.findAuction:GetLinks()
|
||||
local quantity = context.findAuction:GetQuantities()
|
||||
local bidBuyout = nil
|
||||
if context.searchContext:IsBuyoutScan() then
|
||||
bidBuyout = context.findAuction:GetBuyouts()
|
||||
elseif context.searchContext:IsBidScan() then
|
||||
bidBuyout = context.findAuction:GetRequiredBid()
|
||||
else
|
||||
error("Invalid scan type")
|
||||
end
|
||||
if context.searchContext:IsBuyoutScan() then
|
||||
Log.PrintfUser(L["Failed to buy auction of %s (x%s) for %s."], rawLink, quantity, Money.ToString(bidBuyout, nil, "OPT_83_NO_COPPER"))
|
||||
elseif context.searchContext:IsBidScan() then
|
||||
Log.PrintfUser(L["Failed to bid on auction of %s (x%s) for %s."], rawLink, quantity, Money.ToString(bidBuyout, nil, "OPT_83_NO_COPPER"))
|
||||
else
|
||||
error("Invalid scan type")
|
||||
end
|
||||
end
|
||||
context.numConfirmed = context.numConfirmed + (TSM.IsWowClassic() and 1 or context.lastBuyQuantity)
|
||||
context.findAuction = context.scanFrame and context.scanFrame:GetElement("auctions"):GetSelection()
|
||||
return "ST_BIDDING_BUYING", context.lastBuyQuantity
|
||||
end)
|
||||
:AddTransition("ST_BIDDING_BUYING")
|
||||
)
|
||||
:AddDefaultEvent("EV_SCAN_FRAME_SHOWN", function(context, scanFrame)
|
||||
context.scanFrame = scanFrame
|
||||
UpdateScanFrame(context)
|
||||
end)
|
||||
:AddDefaultEvent("EV_SCAN_FRAME_HIDDEN", function(context)
|
||||
context.scanFrame = nil
|
||||
context.findAuction = nil
|
||||
end)
|
||||
:AddDefaultEventTransition("EV_AUCTION_HOUSE_CLOSED", "ST_INIT")
|
||||
:AddDefaultEventTransition("EV_STOP_CLICKED", "ST_INIT")
|
||||
:AddDefaultEvent("EV_AUCTION_ROW_REMOVED", function(context, row)
|
||||
if not row:IsSubRow() then
|
||||
return
|
||||
end
|
||||
row:GetResultRow():RemoveSubRow(row)
|
||||
context.scanFrame:GetElement("auctions"):UpdateData(true)
|
||||
end)
|
||||
:Init("ST_INIT", fsmContext)
|
||||
end
|
||||
|
||||
function private.FSMMessageEventHandler(_, msg)
|
||||
private.fsm:SetLoggingEnabled(false)
|
||||
private.fsm:ProcessEvent("EV_MSG", msg)
|
||||
private.fsm:SetLoggingEnabled(true)
|
||||
end
|
||||
|
||||
function private.FSMBuyoutSuccess()
|
||||
private.fsm:ProcessEvent("EV_BUYOUT_SUCCESS")
|
||||
end
|
||||
|
||||
function private.FSMRescanDelayed()
|
||||
private.fsm:ProcessEvent("EV_RESCAN_DELAYED")
|
||||
end
|
||||
|
||||
function private.FSMScanCallback(success)
|
||||
if success then
|
||||
private.fsm:ProcessEvent("EV_SCAN_COMPLETE")
|
||||
else
|
||||
private.fsm:ProcessEvent("EV_SCAN_FAILED")
|
||||
end
|
||||
end
|
||||
|
||||
function private.FSMPhasedCallback()
|
||||
private.fsm:ProcessEvent("EV_PHASED")
|
||||
end
|
||||
|
||||
function private.FSMFindAuctionCallback(result)
|
||||
if result then
|
||||
private.fsm:ProcessEvent("EV_AUCTION_FOUND", result)
|
||||
else
|
||||
private.fsm:ProcessEvent("EV_AUCTION_NOT_FOUND")
|
||||
end
|
||||
end
|
||||
|
||||
function private.FSMConfirmationCallback(isBuy, quantity)
|
||||
private.fsm:ProcessEvent("EV_CONFIRMED", isBuy, quantity)
|
||||
end
|
||||
Reference in New Issue
Block a user