361 lines
15 KiB
Lua
361 lines
15 KiB
Lua
-- ------------------------------------------------------------------------------ --
|
|
-- TradeSkillMaster --
|
|
-- https://tradeskillmaster.com --
|
|
-- All Rights Reserved - Detailed license information included with addon. --
|
|
-- ------------------------------------------------------------------------------ --
|
|
|
|
local _, TSM = ...
|
|
local Auctioning = TSM.MainUI.Operations:NewPackage("Auctioning")
|
|
local L = TSM.Include("Locale").GetTable()
|
|
local String = TSM.Include("Util.String")
|
|
local Money = TSM.Include("Util.Money")
|
|
local Vararg = TSM.Include("Util.Vararg")
|
|
local CustomPrice = TSM.Include("Service.CustomPrice")
|
|
local UIElements = TSM.Include("UI.UIElements")
|
|
local private = {
|
|
currentOperationName = nil,
|
|
currentTab = nil,
|
|
}
|
|
local IGNORE_DURATION_OPTIONS = {
|
|
L["None"],
|
|
AUCTION_TIME_LEFT1.." ("..AUCTION_TIME_LEFT1_DETAIL..")",
|
|
AUCTION_TIME_LEFT2.." ("..AUCTION_TIME_LEFT2_DETAIL..")",
|
|
AUCTION_TIME_LEFT3.." ("..AUCTION_TIME_LEFT3_DETAIL..")",
|
|
}
|
|
local BELOW_MIN_ITEMS = { L["Don't Post Items"], L["Post at Minimum Price"], L["Post at Maximum Price"], L["Post at Normal Price"], L["Ignore Auctions Below Min"] }
|
|
local BELOW_MIN_KEYS = { "none", "minPrice", "maxPrice", "normalPrice", "ignore" }
|
|
local ABOVE_MAX_ITEMS = { L["Don't Post Items"], L["Post at Minimum Price"], L["Post at Maximum Price"], L["Post at Normal Price"] }
|
|
local ABOVE_MAX_KEYS = { "none", "minPrice", "maxPrice", "normalPrice" }
|
|
local BAD_PRICE_SOURCES = { auctioningopmin = true, auctioningopmax = true, auctioningopnormal = true }
|
|
|
|
|
|
-- ============================================================================
|
|
-- Module Functions
|
|
-- ============================================================================
|
|
|
|
function Auctioning.OnInitialize()
|
|
TSM.MainUI.Operations.RegisterModule("Auctioning", private.GetAuctioningOperationSettings)
|
|
end
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- Auctioning Operation Settings UI
|
|
-- ============================================================================
|
|
|
|
function private.GetAuctioningOperationSettings(operationName)
|
|
TSM.UI.AnalyticsRecordPathChange("main", "operations", "auctioning")
|
|
private.currentOperationName = operationName
|
|
private.currentTab = private.currentTab or L["Details"]
|
|
return UIElements.New("TabGroup", "tabs")
|
|
:SetMargin(0, 0, 8, 0)
|
|
:SetNavCallback(private.GetAuctioningSettings)
|
|
:AddPath(L["Details"])
|
|
:AddPath(L["Posting"])
|
|
:AddPath(L["Canceling"])
|
|
:SetPath(private.currentTab)
|
|
end
|
|
|
|
function private.GetDetailsSettings()
|
|
TSM.UI.AnalyticsRecordPathChange("main", "operations", "auctioning", "details")
|
|
local operation = TSM.Operations.GetSettings("Auctioning", private.currentOperationName)
|
|
return UIElements.New("ScrollFrame", "settings")
|
|
:SetPadding(8, 8, 8, 0)
|
|
:SetBackgroundColor("PRIMARY_BG")
|
|
:AddChild(TSM.MainUI.Operations.CreateExpandableSection("Auctioning", "generalOptions", L["General Options"], L["Adjust some general settings."])
|
|
:AddChild(UIElements.New("Frame", "content")
|
|
:SetLayout("VERTICAL")
|
|
:AddChildrenWithFunction(private.AddMaxStackSizeSetting)
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedSettingLine("ignoreLowDuration", L["Ignore auctions by duration"])
|
|
:SetLayout("VERTICAL")
|
|
:SetHeight(48)
|
|
:SetMargin(0, 0, 0, 16)
|
|
:AddChild(UIElements.New("SelectionDropdown", "dropdown")
|
|
:SetHeight(24)
|
|
:SetDisabled(TSM.Operations.HasRelationship("Auctioning", private.currentOperationName, "ignoreLowDuration"))
|
|
:SetItems(IGNORE_DURATION_OPTIONS)
|
|
:SetSelectedItemByKey(operation.ignoreLowDuration + 1, true)
|
|
:SetScript("OnSelectionChanged", private.IgnoreLowDurationOnSelectionChanged)
|
|
)
|
|
)
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedSettingLine("blacklist", L["Blacklisted players"])
|
|
:SetLayout("VERTICAL")
|
|
:SetHeight(48)
|
|
:AddChild(UIElements.New("Input", "input")
|
|
:SetHeight(24)
|
|
:SetBackgroundColor("ACTIVE_BG")
|
|
:SetHintText(L["Enter player name"])
|
|
:SetDisabled(TSM.Operations.HasRelationship("Auctioning", private.currentOperationName, "blacklist"))
|
|
:SetScript("OnEnterPressed", private.BlacklistInputOnEnterPressed)
|
|
)
|
|
)
|
|
:AddChildrenWithFunction(private.AddBlacklistPlayers)
|
|
)
|
|
)
|
|
:AddChild(TSM.MainUI.Operations.GetOperationManagementElements("Auctioning", private.currentOperationName))
|
|
end
|
|
|
|
function private.AddMaxStackSizeSetting(frame)
|
|
if TSM.IsWowClassic() then
|
|
frame:AddChild(private.CreateToggleLine("matchStackSize", L["Match stack size"]))
|
|
end
|
|
end
|
|
|
|
function private.GetPostingSettings()
|
|
TSM.UI.AnalyticsRecordPathChange("main", "operations", "auctioning", "posting")
|
|
local operation = TSM.Operations.GetSettings("Auctioning", private.currentOperationName)
|
|
return UIElements.New("ScrollFrame", "settings")
|
|
:SetPadding(8, 8, 8, 0)
|
|
:SetBackgroundColor("PRIMARY_BG")
|
|
:AddChild(TSM.MainUI.Operations.CreateExpandableSection("Auctioning", "postingSettings", L["Posting Options"], L["Adjust the settings below to set how groups attached to this operation will be auctioned."])
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedSettingLine("duration", L["Auction duration"])
|
|
:SetLayout("VERTICAL")
|
|
:SetHeight(48)
|
|
:SetMargin(0, 0, 0, 12)
|
|
:AddChild(UIElements.New("SelectionDropdown", "dropdown")
|
|
:SetHeight(24)
|
|
:SetDisabled(TSM.Operations.HasRelationship("Auctioning", private.currentOperationName, "duration"))
|
|
:SetItems(TSM.CONST.AUCTION_DURATIONS)
|
|
:SetSelectedItemByKey(operation.duration)
|
|
:SetScript("OnSelectionChanged", private.SetAuctioningDuration)
|
|
)
|
|
|
|
)
|
|
:AddChild(private.CreateInputLine("postCap", L["Post cap"], false, true))
|
|
:AddChildrenWithFunction(private.AddStackSizeSettings)
|
|
:AddChild(private.CreateInputLine("keepQuantity", L["Amount kept in bags"], false, true))
|
|
:AddChild(private.CreateInputLine("maxExpires", L["Don't post after this many expires"]))
|
|
)
|
|
:AddChild(TSM.MainUI.Operations.CreateExpandableSection("Auctioning", "priceSettings", L["Posting Price"], L["Adjust the settings below to set how groups attached to this operation will be priced."])
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedSettingLine("bidPercent", L["Set bid as percentage of buyout"])
|
|
:SetLayout("VERTICAL")
|
|
:SetHeight(48)
|
|
:SetMargin(0, 0, 0, 12)
|
|
:AddChild(UIElements.New("Frame", "content")
|
|
:SetLayout("HORIZONTAL")
|
|
:SetHeight(24)
|
|
:AddChild(UIElements.New("Input", "input")
|
|
:SetMargin(0, 8, 0, 0)
|
|
:SetBackgroundColor("ACTIVE_BG")
|
|
:SetValidateFunc(private.BidPercentValidateFunc)
|
|
:SetDisabled(TSM.Operations.HasRelationship("Auctioning", private.currentOperationName, "bidPercent"))
|
|
:SetValue((operation.bidPercent * 100).."%")
|
|
:SetScript("OnValueChanged", private.BidPercentOnValueChanged)
|
|
)
|
|
:AddChild(UIElements.New("Text", "label")
|
|
:SetWidth("AUTO")
|
|
:SetFont("BODY_BODY3")
|
|
:SetFormattedText(L["Enter a value from %d - %d%%"], 0, 100)
|
|
:SetTextColor(TSM.Operations.HasRelationship("Auctioning", private.currentOperationName, "bidPercent") and "TEXT_DISABLED" or "TEXT")
|
|
)
|
|
)
|
|
)
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedPriceInput("undercut", L["Undercut amount"], 66, private.CheckUndercut)
|
|
:SetMargin(0, 0, 0, 12)
|
|
)
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedPriceInput("minPrice", L["Minimum price"], 126, BAD_PRICE_SOURCES))
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedSettingLine("priceReset", L["When below minimum:"])
|
|
:SetMargin(0, 0, 12, 12)
|
|
:AddChild(UIElements.New("SelectionDropdown", "dropdown")
|
|
:SetWidth(240)
|
|
:SetDisabled(TSM.Operations.HasRelationship("Auctioning", private.currentOperationName, "priceReset"))
|
|
:SetItems(BELOW_MIN_ITEMS, BELOW_MIN_KEYS)
|
|
:SetSettingInfo(operation, "priceReset")
|
|
)
|
|
)
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedPriceInput("maxPrice", L["Maximum price"], 126, BAD_PRICE_SOURCES))
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedSettingLine("aboveMax", L["When above maximum:"])
|
|
:SetMargin(0, 0, 12, 12)
|
|
:AddChild(UIElements.New("SelectionDropdown", "dropdown")
|
|
:SetWidth(240)
|
|
:SetDisabled(TSM.Operations.HasRelationship("Auctioning", private.currentOperationName, "aboveMax"))
|
|
:SetItems(ABOVE_MAX_ITEMS, ABOVE_MAX_KEYS)
|
|
:SetSettingInfo(operation, "aboveMax")
|
|
)
|
|
)
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedPriceInput("normalPrice", L["Normal price"], 126, BAD_PRICE_SOURCES))
|
|
)
|
|
end
|
|
|
|
function private.AddStackSizeSettings(frame)
|
|
if not TSM.IsWowClassic() then
|
|
return
|
|
end
|
|
frame:AddChild(private.CreateInputLine("stackSize", L["Stack size"], false, true))
|
|
frame:AddChild(private.CreateToggleLine("stackSizeIsCap", L["Allow partial stack"]))
|
|
end
|
|
|
|
function private.GetCancelingSettings()
|
|
TSM.UI.AnalyticsRecordPathChange("main", "operations", "auctioning", "canceling")
|
|
return UIElements.New("ScrollFrame", "settings")
|
|
:SetPadding(8, 8, 8, 0)
|
|
:AddChild(TSM.MainUI.Operations.CreateExpandableSection("Auctioning", "priceSettings", L["Canceling Options"], L["Adjust the settings below to set how groups attached to this operation will be cancelled."])
|
|
:AddChild(private.CreateToggleLine("cancelUndercut", L["Cancel undercut auctions"]))
|
|
:AddChild(private.CreateToggleLine("cancelRepost", L["Cancel to repost higher"]))
|
|
:AddChild(TSM.MainUI.Operations.CreateLinkedPriceInput("cancelRepostThreshold", L["Repost threshold"], 66))
|
|
)
|
|
end
|
|
|
|
function private.GetAuctioningSettings(self, button)
|
|
private.currentTab = button
|
|
if button == L["Details"] then
|
|
return private.GetDetailsSettings()
|
|
elseif button == L["Posting"] then
|
|
return private.GetPostingSettings()
|
|
elseif button == L["Canceling"] then
|
|
return private.GetCancelingSettings()
|
|
else
|
|
error("Unknown button!")
|
|
end
|
|
end
|
|
|
|
function private.AddBlacklistPlayers(frame)
|
|
local operation = TSM.Operations.GetSettings("Auctioning", private.currentOperationName)
|
|
if operation.blacklist == "" then return end
|
|
local containerFrame = UIElements.New("Frame", "blacklistFrame")
|
|
:SetLayout("FLOW")
|
|
for index, player in Vararg.Iterator(strsplit(",", operation.blacklist)) do
|
|
containerFrame:AddChild(UIElements.New("Frame", "blacklist" .. index)
|
|
:SetLayout("HORIZONTAL")
|
|
:SetSize(100, 20)
|
|
:SetMargin(0, 12, 0, 0)
|
|
:AddChild(UIElements.New("Text", "text")
|
|
:SetWidth("AUTO")
|
|
:SetMargin(0, 2, 0, 0)
|
|
:SetFont("BODY_BODY2_MEDIUM")
|
|
:SetText(player)
|
|
)
|
|
:AddChild(UIElements.New("Button", "removeBtn")
|
|
:SetBackgroundAndSize("iconPack.14x14/Close/Circle")
|
|
:SetContext(player)
|
|
:SetScript("OnClick", private.RemoveBlacklistOnClick)
|
|
)
|
|
:AddChild(UIElements.New("Spacer", "spacer"))
|
|
)
|
|
end
|
|
frame:AddChild(containerFrame)
|
|
end
|
|
|
|
function private.CreateInputLine(key, label, disabled, margin)
|
|
local operation = TSM.Operations.GetSettings("Auctioning", private.currentOperationName)
|
|
local hasRelationship = TSM.Operations.HasRelationship("Auctioning", private.currentOperationName, key)
|
|
return TSM.MainUI.Operations.CreateLinkedSettingLine(key, label, disabled)
|
|
:SetLayout("VERTICAL")
|
|
:SetHeight(48)
|
|
:SetMargin(0, 0, 0, margin and 12 or 4)
|
|
:AddChild(UIElements.New("Frame", "content")
|
|
:SetLayout("HORIZONTAL")
|
|
:SetHeight(24)
|
|
:AddChild(UIElements.New("Input", "input")
|
|
:SetMargin(0, 8, 0, 0)
|
|
:SetBackgroundColor("ACTIVE_BG")
|
|
:SetContext(key)
|
|
:SetDisabled(hasRelationship or disabled)
|
|
:SetValidateFunc("CUSTOM_PRICE")
|
|
:SetSettingInfo(operation, key)
|
|
)
|
|
:AddChild(UIElements.New("Text", "label")
|
|
:SetWidth("AUTO")
|
|
:SetFont("BODY_BODY3")
|
|
:SetTextColor((hasRelationship or disabled) and "TEXT_DISABLED" or "TEXT")
|
|
:SetFormattedText(L["Supported value range: %d - %d"], TSM.Operations.Auctioning.GetMinMaxValues(key))
|
|
)
|
|
)
|
|
end
|
|
|
|
function private.CreateToggleLine(key, label)
|
|
local operation = TSM.Operations.GetSettings("Auctioning", private.currentOperationName)
|
|
return TSM.MainUI.Operations.CreateLinkedSettingLine(key, label)
|
|
:SetLayout("VERTICAL")
|
|
:SetHeight(48)
|
|
:SetMargin(0, 0, 0, 12)
|
|
:AddChild(UIElements.New("ToggleOnOff", "toggle")
|
|
:SetHeight(18)
|
|
:SetDisabled(TSM.Operations.HasRelationship("Auctioning", private.currentOperationName, key))
|
|
:SetSettingInfo(operation, key)
|
|
)
|
|
end
|
|
|
|
function private.CheckUndercut(_, value)
|
|
if not TSM.IsWowClassic() and Money.FromString(Money.ToString(value) or value) == 0 then
|
|
return true
|
|
elseif not TSM.IsWowClassic() and (Money.FromString(Money.ToString(value) or value) or math.huge) < COPPER_PER_SILVER then
|
|
return false, L["Invalid undercut. To post below the cheapest auction without a significant undercut, set your undercut to 0c."]
|
|
else
|
|
local isValid, err = CustomPrice.Validate(value)
|
|
if isValid then
|
|
return true
|
|
end
|
|
return false, L["Invalid custom price."].." "..err
|
|
end
|
|
end
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- Local Script Handlers
|
|
-- ============================================================================
|
|
|
|
function private.IgnoreLowDurationOnSelectionChanged(self)
|
|
local operation = TSM.Operations.GetSettings("Auctioning", private.currentOperationName)
|
|
operation.ignoreLowDuration = self:GetSelectedItemKey() - 1
|
|
end
|
|
|
|
function private.BlacklistInputOnEnterPressed(input)
|
|
local newPlayer = input:GetValue()
|
|
if newPlayer == "" or strfind(newPlayer, ",") or newPlayer ~= String.Escape(newPlayer) then
|
|
-- this is an invalid player name
|
|
return
|
|
end
|
|
local operation = TSM.Operations.GetSettings("Auctioning", private.currentOperationName)
|
|
local found = false
|
|
for _, player in Vararg.Iterator(strsplit(",", operation.blacklist)) do
|
|
if newPlayer == player then
|
|
-- this player is already added
|
|
input:SetValue("")
|
|
found = true
|
|
end
|
|
end
|
|
if found then
|
|
return
|
|
end
|
|
operation.blacklist = (operation.blacklist == "") and newPlayer or (operation.blacklist..","..newPlayer)
|
|
input:GetElement("__parent.__parent.__parent.__parent.__parent.__parent"):ReloadContent()
|
|
end
|
|
|
|
function private.RemoveBlacklistOnClick(button)
|
|
local player = button:GetContext()
|
|
-- FIXME: This sort of logic should go within some Auctioning-specific operation setting wrapper code
|
|
local operation = TSM.Operations.GetSettings("Auctioning", private.currentOperationName)
|
|
if operation.blacklist == player then
|
|
operation.blacklist = ""
|
|
else
|
|
-- handle cases where this entry is at the start, in the middle, and at the end
|
|
operation.blacklist = gsub(operation.blacklist, "^"..player..",", "")
|
|
operation.blacklist = gsub(operation.blacklist, ","..player..",", ",")
|
|
operation.blacklist = gsub(operation.blacklist, ","..player.."$", "")
|
|
end
|
|
button:GetElement("__parent.__parent.__parent.__parent.__parent.__parent.__parent"):ReloadContent()
|
|
end
|
|
|
|
function private.SetAuctioningDuration(dropdown)
|
|
local operation = TSM.Operations.GetSettings("Auctioning", private.currentOperationName)
|
|
operation.duration = dropdown:GetSelectedItemKey()
|
|
end
|
|
|
|
function private.BidPercentValidateFunc(_, value)
|
|
value = strmatch(value, "^([0-9]+) *%%?$")
|
|
value = tonumber(value)
|
|
if not value or value < 0 or value > 100 then
|
|
return false, L["Bid percent must be between 0 and 100."]
|
|
end
|
|
return true
|
|
end
|
|
|
|
function private.BidPercentOnValueChanged(input)
|
|
local operation = TSM.Operations.GetSettings("Auctioning", private.currentOperationName)
|
|
local value = strmatch(input:GetValue(), "^([0-9]+) *%%?$")
|
|
value = tonumber(value) / 100
|
|
operation.bidPercent = value
|
|
end
|